← 返回题目列表

INNER JOIN、LEFT JOIN、RIGHT JOIN 和 FULL JOIN 有什么区别?

高频 简单 第 2 / 28 题 更新于 2026/07/27
SQLJOIN表连接

简化版

INNER JOIN 只保留两边匹配的行;LEFT JOIN 保留左表全部行;RIGHT JOIN 保留右表全部行;FULL OUTER JOIN 保留两边全部行,未匹配一侧补 NULL。MySQL 目前没有直接支持 FULL OUTER JOIN,需要用其他写法模拟。

详细版

假设 department 是部门表,employee 是员工表,两者用 department_id 关联:

连接类型返回结果
INNER JOIN只返回有对应部门的员工与有员工匹配的部门
LEFT JOIN返回左表全部行,右表无匹配时补 NULL
RIGHT JOIN返回右表全部行,左表无匹配时补 NULL
FULL OUTER JOIN返回两表所有行,任一侧无匹配都补 NULL
CROSS JOIN返回笛卡尔积,即两表行数相乘

连接条件应优先写在 ON 中。对外连接而言,把右表条件写进 WHERE 可能过滤掉补出的 NULL 行,使结果效果接近内连接。

完整版教学

一、INNER JOIN 只要交集

SELECT e.name, d.name AS department_name
FROM employee AS e
INNER JOIN department AS d
  ON d.id = e.department_id;

只有 e.department_id = d.id 成立的组合才会进入结果。一个部门有多名员工时,部门行会与每名员工分别配对,因此连接结果不保证与任一原表行数相同。

二、LEFT JOIN 保住左表

SELECT d.name, e.name AS employee_name
FROM department AS d
LEFT JOIN employee AS e
  ON e.department_id = d.id;

即使某个部门没有员工,它也会出现一次,此时员工列为 NULL。查“没有员工的部门”可以在连接后判断右表主键:

SELECT d.*
FROM department AS d
LEFT JOIN employee AS e ON e.department_id = d.id
WHERE e.id IS NULL;

应判断右表中确定非空的列,主键最合适;若判断本身允许为 NULL 的业务列,会误判。

三、RIGHT JOIN 与 FULL OUTER JOIN

RIGHT JOIN 与交换左右表后的 LEFT JOIN 等价。团队通常统一使用 LEFT JOIN,可降低阅读时切换主表视角的成本。

FULL OUTER JOIN 同时保住两边。PostgreSQL、Oracle 等支持该语法;MySQL 不直接支持。MySQL 中可按业务需求用“左连接结果 + 仅右侧未匹配行”的 UNION ALL 模拟,不能简单把两个完整外连接结果拼接,否则匹配行会重复。

四、ON 条件和 WHERE 条件的陷阱

下面两条对 LEFT JOIN 的含义不同:

-- 保留所有部门,只连接在职员工
LEFT JOIN employee AS e
  ON e.department_id = d.id AND e.status = 'active'

-- 连接完成后只保留在职员工,空部门也被过滤
LEFT JOIN employee AS e ON e.department_id = d.id
WHERE e.status = 'active'

第二种写法会拒绝 e.statusNULL 的补齐行,通常等效于内连接效果。是否应该这样写取决于业务语义,而不是固定规则。

五、连接为什么会产生重复行

SQL 连接按匹配组合输出。一对多连接会让“一”侧重复,多对多连接可能迅速放大行数。发现重复时应先检查关系基数和连接条件是否完整,而不是立即加 DISTINCT 掩盖问题。

连接列通常需要合适索引,但最终访问方式仍由数据量、选择性和优化器成本决定。索引也不能修复漏写连接条件造成的笛卡尔积。

六、常见误区与追问

连接类型保留规则无匹配时
INNER JOIN只保留匹配行两侧不匹配都丢弃
LEFT JOIN保留左表行右表列补 NULL
RIGHT JOIN保留右表行左表列补 NULL
FULL OUTER JOIN两侧都保留不匹配侧补 NULL
  • 误区:LEFT JOIN 后在 WHERE 写右表条件仍然保留左表全部行。 WHERE right_col = ... 会把补出来的 NULL 行过滤掉,效果可能退化为内连接。
  • 误区:JOIN 只会按两表主键一对一合并。 连接按匹配关系组合行,一对多、多对多都会放大行数,重复通常来自数据关系而不是数据库出错。
  • 误区:RIGHT JOIN 比 LEFT JOIN 有特殊能力。 二者只是保留侧不同,多数场景可通过交换表顺序改写成 LEFT JOIN,可读性更稳定。
  • 追问:FULL OUTER JOIN 适合什么场景? 需要同时保留两侧不匹配数据时使用,例如对账时找左有右无、右有左无以及双方匹配的记录。
  • 追问:ON 和 WHERE 的核心区别是什么? ON 决定两表如何匹配并影响外连接补空,WHERE 是连接结果形成后的过滤。
  • 追问:怎样避免连接后聚合被放大? 先确认基数关系,必要时先在子查询中把多方聚合到一行,再与主表连接。

记忆钩子:内连接看匹配,外连接看保留侧;外连接最怕把右表过滤条件错放到 WHERE

七、加强记忆

INNER 取匹配交集,LEFT 保左,RIGHT 保右,FULL 保两边,CROSS 做组合。外连接最容易错在过滤位置:ON 决定右侧哪些行参与匹配,WHERE 对连接后的整份结果再次过滤,可能把补出的 NULL 行一起删掉。