mysql中LEFT JOIN与RIGHT JOIN的差异与选择

来源:这里教程网 时间:2026-02-28 20:40:08 作者:

LEFT JOIN 和 RIGHT JOIN 的本质区别在哪?

本质就一条:谁是主表(保留全部记录的表),谁是从表(只填匹配项,不匹配就 NULL)。

LEFT JOIN
FROM 后第一个表(左表)为主表
RIGHT JOIN
则以 JOIN 后那个表(右表)为主表。其他逻辑完全对称——不是“功能不同”,而是“主次关系翻转”。

SELECT * FROM A LEFT JOIN B ON A.id = B.a_id
→ A 全出,B 匹配不上就 NULL
SELECT * FROM A RIGHT JOIN B ON A.id = B.a_id
→ B 全出,A 匹配不上就 NULL
二者结果集可以完全等价:把表顺序调换 + 改用 LEFT JOIN 就能替代 RIGHT JOIN(例如
SELECT * FROM B LEFT JOIN A ON A.id = B.a_id

实际开发中为什么几乎不用 RIGHT JOIN?

不是它不能用,而是它容易引发阅读和维护陷阱。人脑读 SQL 习惯从左到右,

FROM A RIGHT JOIN B
看着像“先查 A 再右连 B”,但实际语义却是“以 B 为主”,反直觉。团队协作时,别人扫一眼容易误判主表意图。

绝大多数 LEFT JOIN 场景都能通过调整表顺序重写为 LEFT JOIN,更符合思维惯性 MySQL 执行器对
LEFT JOIN
RIGHT JOIN
的优化路径一致,性能无差异
部分 ORM(如 Django ORM、MyBatis Plus)默认只生成 LEFT JOIN,不支持显式 RIGHT JOIN 语法 代码审查时,遇到 RIGHT JOIN 往往会被要求重构 —— 不是错,是“不够清晰”

什么时候必须用 RIGHT JOIN?

几乎没有“必须”。但极少数场景下,若强行用 LEFT JOIN 会导致嵌套过深或别名混乱,可权衡使用。例如:已有复杂子查询作为左表,又想以右侧基础维表(如

dim_region
)为基准补全所有区域信息,此时写
(subquery) RIGHT JOIN dim_region
可避免把子查询再包一层
FROM

SELECT u.name, r.region_name
FROM (
  SELECT user_id, name FROM users WHERE status = 1
) u
RIGHT JOIN dim_region r ON u.region_id = r.id;

但更推荐写法仍是把维表放前面:

SELECT u.name, r.region_name
FROM dim_region r
LEFT JOIN users u ON u.region_id = r.id AND u.status = 1;

LEFT JOIN 中 ON 和 WHERE 的坑你踩过吗?

这是比 LEFT/RIGHT 选择更常翻车的地方:

ON
是连接时过滤右表;
WHERE
是连接后过滤整行。一旦在 LEFT JOIN 后加了
WHERE 右表字段 IS NOT NULL
,就事实退化成 INNER JOIN。

错误写法(本想查所有部门 + 员工数,却漏掉无人部门):
SELECT d.name, COUNT(e.id) FROM dept d LEFT JOIN emp e ON d.id = e.dept_id WHERE e.id IS NOT NULL GROUP BY d.name;
正确写法(保留 NULL 部门):
SELECT d.name, COUNT(e.id) FROM dept d LEFT JOIN emp e ON d.id = e.dept_id GROUP BY d.name;
想筛“有员工的部门”?直接用
INNER JOIN
,语义更干净

LEFT JOIN 的真正价值,在于“保左表完整性”;一旦 WHERE 拿右表字段做非 NULL 判断,这个保证就失效了——这点比纠结 LEFT 还是 RIGHT 重要得多。

相关推荐