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 重要得多。

相关推荐