深入解析:SQL连接类型解析:从交集到并集
核心概念总结
INNER JOIN(内连接):只返回两个表中连接条件匹配 的行。取的是两个表的“交集”。
LEFT JOIN(左连接):返回左表的所有行,以及右表中连接条件匹配的行。如果右表没有匹配的行,则结果集中右表的列返回
NULL。它关注的是“左表的全部”。RIGHT JOIN(右连接):与左连接相反。返回右表的所有行,以及左表中连接条件匹配的行。如果左表没有匹配的行,则结果集中左表的列返回
NULL。它关注的是“右表的全部”。FULL OUTER JOIN(全外连接):返回左表和右表中的所有行。当某一行在另一个表中没有匹配时,另一个表的列将包含
NULL。它取的是两个表的“并集”。
举例说明
假设我们有两个简单的表:
Customers 表(左表)
| customer_id | name |
|---|---|
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
Orders 表(右表)
| order_id | amount | customer_id | |
|---|---|---|---|
| 101 | 200 | 1 | |
| 102 | 500 | 2 | |
| 103 | 300 | 1 | |
| 104 | 800 | 4 | (注意:客户4在Customers表中不存在) |
1. INNER JOIN(内连接)
查询: 找出所有客户及其对应的订单(只找有订单的客户和有客户的订单)。
SELECT
Customers.name,
Orders.order_id,
Orders.amount
FROM Customers
INNER JOIN Orders ON Customers.customer_id = Orders.customer_id;
结果:
| name | order_id | amount |
|---|---|---|
| 张三 | 101 | 200 |
| 张三 | 103 | 300 |
| 李四 | 102 | 500 |
解释:
只返回了
Customers表和Orders表中customer_id能匹配上的行。王五没有订单,所以没有出现。订单
104的客户4在客户表中不存在,所以也没有出现。
2. LEFT JOIN(左连接)
查询: 列出所有客户,以及他们下的订单(即使客户一个订单也没有)。
SELECT
Customers.name,
Orders.order_id,
Orders.amount
FROM Customers
LEFT JOIN Orders ON Customers.customer_id = Orders.customer_id;
结果:
| name | order_id | amount |
|---|---|---|
| 张三 | 101 | 200 |
| 张三 | 103 | 300 |
| 李四 | 102 | 500 |
| 王五 | NULL | NULL |
解释:
左表
Customers的所有记录都被返回。张三和李四有匹配的订单,所以订单信息正常显示。王五没有订单,所以在Orders表的列(order_id,amount)上用NULL填充。订单
104依然没有出现,因为它不属于任何左表中的客户。
3. RIGHT JOIN(右连接)
查询: 列出所有订单,以及对应的客户信息(即使订单找不到对应的客户)。
SELECT
Customers.name,
Orders.order_id,
Orders.amount
FROM Customers
RIGHT JOIN Orders ON Customers.customer_id = Orders.customer_id;
结果:
| name | order_id | amount |
|---|---|---|
| 张三 | 101 | 200 |
| 李四 | 102 | 500 |
| 张三 | 103 | 300 |
NULL | 104 | 800 |
解释:
右表
Orders的所有记录都被返回。订单
101,102,103都找到了对应的客户。订单
104的客户4在Customers表中不存在,所以在Customers表的列(name)上用NULL填充。王五没有出现在结果中,因为右表Orders里没有他的订单。
4. FULL OUTER JOIN(全外连接)
查询: 列出所有客户和所有订单,不管它们之间是否有关系。
-- 注意:MySQL不支持FULL OUTER JOIN,但其他数据库如PostgreSQL, SQL Server支持。
SELECT
Customers.name,
Orders.order_id,
Orders.amount
FROM Customers
FULL OUTER JOIN Orders ON Customers.customer_id = Orders.customer_id;
结果:
| name | order_id | amount |
|---|---|---|
| 张三 | 101 | 200 |
| 李四 | 102 | 500 |
| 张三 | 103 | 300 |
| 王五 | NULL | NULL |
NULL | 104 | 800 |
解释:
它结合了 LEFT JOIN 和 RIGHT JOIN 的结果。
既包含了所有客户(即使没订单),也包含了所有订单(即使没客户)。
总结与类比(使用集合韦恩图)
可以想象两个圆圈:
左圈:
Customers表右圈:
Orders表重叠部分:
customer_id匹配的行
| 连接类型 | 相当于取... | 描述 |
|---|---|---|
| INNER JOIN | 重叠部分 | 只关心有关系的记录 |
| LEFT JOIN | 左圈全部 | 关心左表全部,右表只是补充信息 |
| RIGHT JOIN | 右圈全部 | 关心右表全部,左表只是补充信息 |
| FULL OUTER JOIN | 两个圈所有部分 | 所有数据我都要,不管有没有关系 |
其他连接
CROSS JOIN(交叉连接):返回两个表的笛卡尔积,即左表的每一行与右表的每一行进行组合。结果集的行数 = 左表行数 × 右表行数。通常需要避免无意中使用。
SELF JOIN(自连接):本质上是将一个表与它自己进行连接(通常是内连接或左连接),常用于查询有层级关系的数据,比如员工和经理都在同一个
Employees表中。
SELF JOIN(自连接)
核心概念
SELF JOIN 是指一个表与自身进行连接。它不是一种特殊的 JOIN 语法,而是一种技术。你可以使用 INNER JOIN、LEFT JOIN 等任何连接类型来实现自连接。
为什么要自连接?
当表中的记录之间存在内部关系时,就需要自连接。
总结对比
| 特性 | CROSS JOIN | SELF JOIN |
|---|---|---|
| 本质 | 两个不同表的笛卡尔积 | 同一个表与自身连接 |
| 连接条件 | 不需要 ON 子句 | 需要 ON 子句来定义表内关系 |
| 结果集大小 | 行数 = 表A行数 × 表B行数 | 取决于连接条件和连接类型 |
| 主要用途 | 生成所有组合、测试数据 | 查询层级关系、内部关联 |
| 语法特点 | 可省略 ON 子句 | 必须使用表别名 |
语法
由于是同一个表,必须使用表别名来区分两个"实例"。
SELECT
A.column1,
B.column2
FROM table_name A
JOIN table_name B ON A.common_column = B.common_column;
示例:员工层级关系
Employees 表
| emp_id | name | manager_id |
|---|---|---|
| 1 | Alice | NULL |
| 2 | Bob | 1 |
| 3 | Carol | 1 |
| 4 | David | 2 |
查询: 找出每个员工及其经理的名字
SELECT
E.name AS employee_name,
M.name AS manager_name
FROM Employees E
LEFT JOIN Employees M ON E.manager_id = M.emp_id;
结果:
| employee_name | manager_name |
|---|---|
| Alice | NULL |
| Bob | Alice |
| Carol | Alice |
| David | Bob |
更多自连接示例
查询有相同经理的员工对:
SELECT
A.name AS employee1,
B.name AS employee2,
M.name AS manager_name
FROM Employees A
JOIN Employees B ON A.manager_id = B.manager_id AND A.emp_id < B.emp_id
JOIN Employees M ON A.manager_id = M.emp_id;
结果:
| employee1 | employee2 | manager_name |
|---|---|---|
| Bob | Carol | Alice |
使用场景
层级关系查询(组织架构、分类树)
查找相似或相关的记录
分析序列或时间线数据
查找重复或模式匹配
CROSS JOIN(交叉连接)
核心概念
CROSS JOIN 返回两个表的笛卡尔积。这意味着左表中的每一行都会与右表中的每一行进行组合。它不需要任何连接条件(ON子句)。
语法
SELECT * FROM table1 CROSS JOIN table2; -- 或者使用隐式语法(不推荐,容易混淆) SELECT * FROM table1, table2;示例
假设我们有两个小表:
Colors表color_id color_name 1 Red 2 Blue Sizes表size_id size_name S Small M Medium L Large CROSS JOIN 查询:
SELECT Colors.color_name, Sizes.size_name FROM Colors CROSS JOIN Sizes;结果:
color_name size_name Red Small Red Medium Red Large Blue Small Blue Medium Blue Large 结果集行数 = 2 colors × 3 sizes = 6行
使用场景
生成所有可能的组合(如上面的颜色和尺寸例子)
创建测试数据
生成序列或矩阵
进行系统性的计算(如每个产品在所有地区的销售目标)
如果表很大,CROSS JOIN 会产生极其庞大的结果集
要谨慎使用,确保这是你真正需要的

浙公网安备 33010602011771号