内连接、左连接、右连接有什么区别?
理解内连接、左连接和右连接的区别是掌握 SQL 查询的核心。它们主要决定了当两个表基于某个关联条件连接时,哪些行会被包含在结果集中。
现在我们有2个表:
员工表 (Employees)
id | name | department_id |
1 | 张三 | 1 |
2 | 李四 | 1 |
3 | 王五 | 2 |
4 | 赵六 | 3 |
5 | 钱七 | NULL |
部门表 (Departments)
id | department_name |
1 | 技术部 |
2 | 市场部 |
4 | 财务部 |
关联条件: Employees.department_id = Departments.id
1. 内连接 (INNER JOIN)
核心思想: 只返回两个表中连接条件完全匹配的行。它是交集。
结果集包含:
员工表中有部门ID (
department_id
非空) 且该部门ID在部门表中存在 (
id
匹配)。结果示例 (基于我们的表):
id | name | department_id | department_name |
---|---|---|---|
1 | 张三 | 1 | 技术部 |
2 | 李四 | 1 | 技术部 |
3 | 王五 | 2 | 市场部 |
谁被排除了?
赵六 (
department_id=3
,但部门表中没有id=3
的部门) - 右表无匹配钱七 (
department_id=NULL
,无法匹配任何部门ID) - 左表条件无效财务部 (
id=4
,但没有员工department_id=4
) - 左表无匹配
SELECT Employees.id, Employees.name, Employees.department_id, Departments.department_nameFROM Employees INNER JOIN Departments ON Employees.department_id = Departments.id;
2. 左连接 (LEFT JOIN 或 LEFT OUTER JOIN)
核心思想: 返回左表 (FROM子句后的表) 的所有行,即使在右表 (JOIN子句后的表) 中没有匹配的行。对于右表无匹配的行,结果集中右表的所有列将显示为
NULL
。结果集包含:
所有左表 (员工表) 的行。
如果员工在部门表中有匹配的部门,则显示部门信息。
如果员工在部门表中没有匹配的部门(
department_id
在部门表中找不到对应id
或department_id
是NULL
),则部门信息列显示为NULL
。结果示例 (基于我们的表):
id name department_id department_name 1 张三 1 技术部 2 李四 1 技术部 3 王五 2 市场部 4 赵六 3 NULL <-- 部门ID 3 在部门表中不存在 5 钱七 NULL NULL <-- 没有部门ID,无法匹配 谁被排除了?
财务部 (
id=4
,但没有员工department_id=4
) - 右表行在左表无匹配
SELECT Employees.id, Employees.name, Employees.department_id, Departments.department_name FROM Employees LEFT JOIN Departments ON Employees.department_id = Departments.id;
3. 右连接 (RIGHT JOIN 或 RIGHT OUTER JOIN)
核心思想: 返回右表 (JOIN子句后的表) 的所有行,即使在左表 (FROM子句后的表) 中没有匹配的行。对于左表无匹配的行,结果集中左表的所有列将显示为
NULL
。结果集包含:
所有右表 (部门表) 的行。
如果部门在员工表中有匹配的员工(有员工的
department_id
等于该部门的id
),则显示员工信息。如果部门在员工表中没有匹配的员工(没有员工的
department_id
等于该部门的id
),则员工信息列显示为NULL
。结果示例 (基于我们的表):
id name department_id department_name 1 张三 1 技术部 2 李四 1 技术部 3 王五 2 市场部 NULL NULL NULL 财务部 <-- 部门ID 4 没有对应的员工 谁被排除了?
赵六 (
department_id=3
,但部门表中没有id=3
的部门) - 左表行在右表无匹配钱七 (
department_id=NULL
,无法匹配任何部门ID) - 左表行在右表无匹配
SELECT Employees.id, Employees.name, Employees.department_id, Departments.department_name FROM Employees RIGHT JOIN Departments ON Employees.department_id = Departments.id;
关键区别总结表
特性 | 内连接 (INNER JOIN) | 左连接 (LEFT JOIN) | 右连接 (RIGHT JOIN) |
---|---|---|---|
核心原则 | 只返回匹配行 | 返回左表所有行 + 匹配的右表行 | 返回右表所有行 + 匹配的左表行 |
结果集来源 | 两表的交集 | 左表全集 + 匹配的右表子集 | 右表全集 + 匹配的左表子集 |
未匹配处理 | 双方不匹配的行都不包含 | 左表未匹配行保留,右表列置为 NULL | 右表未匹配行保留,左表列置为 NULL |
使用频率 | 非常高 | 非常高 | 相对较少 (可用左连接替代) |
类似概念 | 交集 | 左表全集 | 右表全集 |
简单记忆
INNER JOIN: “两边都要有”(严格匹配)。
LEFT JOIN: “左边全要,右边有的就给,没有就给空”。
RIGHT JOIN: “右边全要,左边有的就给,没有就给空”(实践中通常用
LEFT JOIN
调换表顺序来实现,避免使用RIGHT JOIN
使查询逻辑更清晰)。