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 匹配不上就 NULLSELECT * FROM A RI
GHT JOIN B ON A.id = B.a_id → B 全出,A 匹配不上就 NULLSELECT * FROM B LEFT JOIN A ON A.id = B.a_id)不是它不能用,而是它容易引发阅读和维护陷阱。人脑读 SQL 习惯从左到右,FROM A RIGHT JOIN B 看着像“先查 A 再右连 B”,但实际语义却是“以 B 为主”,反直觉。团队协作时,别人扫一眼容易误判主表意图。
LEFT 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/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;
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 重要得多。