图解SQL inner join、left join、right join、full outer join、union、union all的区别

本文详细解释了SQL中的不同Join类型,包括INNER JOIN、FULL OUTER JOIN、LEFT OUTER JOIN和RIGHT OUTER JOIN等,并通过具体例子展示了每种Join操作的效果及应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转于:http://justcoding.iteye.com/blog/2006487

这是一篇来自Coding Horror的文章。

 

SQL的Join语法有很多:有inner的,有outer的,有left的,有时候,对于Select出来的结果集是什么样子有点不是很清楚。

 

假设我们有两张表。Table A是左边的表,Table B是右边的表。其各有四条记录,其中有两条记录name是相同的,如下所示:

A表
id name
1 Pirate
2 Monkey
3 Ninja
4 Spaghetti
B表
id name
1 Rutabaga
2 Pirate
3 Darth Vade
4 Ninja

 

1、INNER JOIN

SELECT * FROM TableA INNER JOIN TableB ON TableA.name = TableB.name

结果集
(TableA.) (TableB.)
id name id name
1 Pirate 2 Pirate
3 Ninja 4 Ninja

Inner join 产生的结果集是A和B的交集

Inner join产生的结果集是A和B的交集。

 
2、FULL [OUTER] JOIN

(1) SELECT * FROM TableA FULL OUTER JOIN TableB ON TableA.name = TableB.name

结果集
(TableA.) (TableB.)
id name id name
1 Pirate 2 Pirate
2 Monkey null null
3 Ninja 4 Ninja
4 Spaghetti null null
null null 1 Rutabaga
null null 3 Darth Vade

Full outer join 产生A和B的并集

Full outer join产生A和B的并集。但是需要注意的是,对于没有匹配的记录,则会以null做为值。可以使用IFNULL判断。

 

注意:

mysql 不支持全连接full join 的数据库,可以用union 来代替:

1
2
3
select  from  hx_user  LEFT  JOIN  hx_admin  on  hx_user. name  = hx_admin.admin_name
UNION
SELECT  from  hx_user  RIGHT  JOIN  hx_admin  on  hx_user. name  = hx_admin.admin_name;

 

 

(2) SELECT * FROM TableA FULL OUTER JOIN TableB ON TableA.name = TableB.name WHERE TableA.id IS null OR TableB.id IS null

结果集
(TableA.) (TableB.)
id name id name
2 Monkey null null
4 Spaghetti null null
null null 1 Rutabaga
null null 3 Darth Vade

产生A表和B表没有交集的数据集

产生A表和B表没有交集的数据集。

1
2
3
select  from  hx_user  LEFT  JOIN  hx_admin  on  hx_user. name  = hx_admin.admin_name  where  hx_user. name  is  NULL  or  hx_admin.admin_name  is  NULL
UNION
SELECT  from  hx_user  RIGHT  JOIN  hx_admin  on  hx_user. name  = hx_admin.admin_name  where  hx_user. name  is  NULL  or  hx_admin.admin_name  is  NULL

 

 

3、LEFT [OUTER] JOIN

(1) SELECT * FROM TableA LEFT OUTER JOIN TableB ON TableA.name = TableB.name

结果集
(TableA.) (TableB.)
id name id name
1 Pirate 2 Pirate
2 Monkey null null
3 Ninja 4 Ninja
4 Spaghetti null null

eft outer join 产生表A的完全集,而B表中匹配的则有值

Left outer join产生表A的完全集,而B表中匹配的则有值,没有匹配的则以null值取代。

 

(2) SELECT * FROM TableA LEFT OUTER JOIN TableB ON TableA.name = TableB.name WHERE TableB.id IS null

结果集
(TableA.) (TableB.)
id name id name
2 Monkey null null
4 Spaghetti null null

产生在A表中有而在B表中没有的集合

 

4、RIGHT [OUTER] JOIN

RIGHT OUTERJOIN是后面的表为基础,与LEFT OUTER JOIN用法类似。这里不介绍了。

 

5、UNION  UNION ALL

UNION操作符用于合并两个或多个SELECT语句的结果集。 请注意,UNION内部的SELECT语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条SELECT语句中的列的顺序必须相同。 UNION只选取记录,而UNION ALL会列出所有记录。

 

(1) SELECT name FROM TableA UNION SELECT name FROM TableB

新结果集
name
Pirate
Monkey
Ninja
Spaghetti
Rutabaga
Darth Vade

选取不同值

 

(2) SELECT name FROM TableA UNION ALL SELECT name FROM TableB

新结果集
name
Pirate
Monkey
Ninja
Spaghetti
Rutabaga
Pirate
Darth Vade
Ninja

全部列出来

 

(3) 注意:SELECT * FROM TableA UNION SELECT * FROM TableB

新结果集
id name
1 Pirate
2 Monkey
3 Ninja
4 Spaghetti
1 Rutabaga
2 Pirate
3 Darth Vade
4 Ninja

由于id 1 Pirate与id 2 Pirate并不相同,不合并。

还需要注册的是我们还有一个是“交差集”cross join,这种join没有办法用文式图表示,因为其就是把表A和表B的数据进行一个N*M的组合,即笛卡尔积。表达式如下:SELECT * FROM TableA CROSS JOIN TableB,这个笛卡尔乘积会产生4 x 4 = 16条记录,一般来说,我们很少用到这个语法。但是我们得小心,如果不是使用嵌套的select语句,一般系统都会产生笛卡尔乘积然再做过滤。这是对于性 能来说是非常危险的,尤其是表很大的时候。

### 不同SQL连接类型的定义区别 #### 定义基本功能 在关系型数据库中,`JOIN` 是一种用于组合两个或多个表的数据的操作。通过指定条件,可以从不同的表中提取所需的信息。 - **INNER JOIN(内连接)** `INNER JOIN` 返回的结果集仅包含那些满足连接条件的记录。换句话说,只有当两张表中的数据能够匹配上时,才会被返回[^2]。如果某张表中有不匹配的行,则这些行不会出现在最终结果集中。 - **LEFT JOIN(左外连接)** 左外连接会返回左边表 (`FROM` 子句后面的第一个表) 所有的记录以及右边表中符合条件的记录;对于右边表中没有对应匹配项的情况,在结果集中对应的字段会被填充为 NULL 值[^3]。 - **RIGHT JOIN(右外连接)** 右外连接的行为类似于左外连接,但它优先考虑的是右侧表(`ON`关键字后的第二个表),即它将保留右侧表所有的记录,并补充左侧表中存在的匹配部分或者用NULL填补缺失的部分[^4]。 #### 使用方法举例 以下是每种类型的具体应用实例: ```sql -- INNER JOIN 示例 SELECT * FROM employees e INNER JOIN departments d ON e.department_id = d.id; ``` 上述语句表示从员工(employee) 表和部门(department) 表里选出所有有共同 department_id 的条目。 ```sql -- LEFT JOIN 示例 SELECT students.name, classes.class_name FROM students LEFT JOIN classes ON students.class_id = classes.id; ``` 此查询显示学生的名字及其所属班级名称。即使某些学生的 class_id 并不存在于classes表之中,他们仍然会在输出列表里面出现,只是class_name列为空(NULL)。 ```sql -- RIGHT JOIN 示例 SELECT products.product_name, suppliers.supplier_name FROM products RIGHT JOIN suppliers ON products.supplier_id = suppliers.id; ``` 这里我们获取产品名连同一个供应商名字。如果有任何供应者未提供具体的产品信息,那么相应位置上的product_name将是null值。 #### 图解差异 为了更直观理解这几种连接方式之间的差别,可以通过图形化的方式来展示它们的工作原理。通常情况下,可以用Venn Diagrams来代表各个集合间的关系。例如,下图展示了四种主要形式如何相互作用并影响最终得到的数据子集[^5]: ![Join Types](https://i.imgur.com/yourimage.png) 请注意实际链接可能有所不同,请自行查找合适的图片资源替换占位符URL地址。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值