LEFT JOIN 以左表为主表,RIGHT JOIN 以右表为主表,本质是主表选择不同;二者逻辑对称,可相互转换;实际开发中因可读性差、反直觉而极少使用。

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










