left join 保留左表全部行(右表无匹配时字段为 null),inner join 仅返回两表交集;right join 可用 left join 替代,on 中右表条件影响连接逻辑,where 中则过滤结果。

LEFT JOIN 和 INNER JOIN 的核心区别在于:是否强制要求右表有匹配行。用一句话说:只要左表某行在右表找不到匹配,LEFT JOIN 仍保留它(右表字段填 NULL),而 INNER JOIN 直接丢弃。
LEFT JOIN 保留左表全部数据,哪怕右表没对应记录
当你需要“主表完整、附表可选”的语义时,必须用 LEFT JOIN。比如查所有用户及其订单信息,即使某些用户从未下单,也要显示出来。
- 结果集行数恒等于左表行数(不管右表有没有匹配)
- 右表字段在无匹配时为
NULL,后续对这些字段做WHERE过滤要格外小心(见下一点) - 常见误写:
SELECT * FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE o.status = 'paid'—— 这会把所有o.status为NULL的行过滤掉,实际变成INNER JOIN效果
INNER JOIN 只返回两表都满足条件的交集
INNER JOIN 是最严格的连接,它不承诺保留任何一方的完整性,只关心“两边都有”。适合关联强依赖场景,比如查订单详情时必须同时存在商品信息。
- 结果集行数 ≤ 左表行数,也 ≤ 右表行数;具体取决于匹配数量
- 没有
NULL值来自连接逻辑本身(除非原始数据就有) - 性能通常优于
LEFT JOIN,尤其当连接字段有索引且匹配率高时 - 注意:隐式写法
FROM a, b WHERE a.id = b.parent_id等价于INNER JOIN,但已不推荐——可读性差、易漏条件、难维护
WHERE 条件放 ON 还是放 WHERE,结果可能完全不同
这是最容易出错的地方。对右表的过滤条件,放在 ON 子句和放在 WHERE 子句,语义差异极大。
-
LEFT JOIN ... ON a.id = b.user_id AND b.status = 'paid':只影响匹配逻辑,左表所有行仍在,只是只有status = 'paid'的右表行才参与连接 -
LEFT JOIN ... ON a.id = b.user_id WHERE b.status = 'paid':先连接再过滤,b.status为NULL的行被干掉,等效于INNER JOIN - 简单记法:想“右表参与连接的门槛”,写进
ON;想“最终结果的全局筛选”,才写进WHERE
RIGHT JOIN 几乎没必要用,LEFT JOIN 就够了
虽然语法上 RIGHT JOIN 存在,但它的行为完全可以用调换表顺序 + LEFT JOIN 实现。强行用 RIGHT JOIN 容易让阅读者多绕半秒,还可能在嵌套多表时搞混基准表。
- 例如:
SELECT * FROM a RIGHT JOIN b ON a.id = b.a_id等价于SELECT * FROM b LEFT JOIN a ON b.a_id = a.id - 团队协作中,统一用
LEFT JOIN并把主表(你要保证其完整性的表)放左边,能显著降低理解成本 - 有些数据库或 ORM 对
RIGHT JOIN支持较弱,或生成执行计划不如LEFT JOIN稳定
真正容易被忽略的,是 ON 里加右表条件这件事——它不像直觉那么“安全”,但却是控制外连接行为最精细的开关。写完 LEFT JOIN,务必检查每个右表字段的过滤位置。










