SQLPathLab
SQL 实战指南 · MySQL 8.0

LEFT JOIN 条件写在 ON 还是 WHERE

右表条件的位置会决定未匹配的左表行是否保留。

问题与判断方法

LEFT JOIN 的 ON 先决定哪些右表记录可以匹配,未匹配时右表字段变为 NULL。之后 WHERE 再筛选完整结果;如果 WHERE 要求右表字段满足某个值,NULL 行会被删除,结果就可能接近 INNER JOIN。

需要保留左表全部记录时,把只限制右表匹配资格的条件写进 ON。确实只要存在符合条件的右表记录时,写在 WHERE 才符合语义。

判断位置不要依赖固定口诀,而要先写清楚问题:没有匹配记录的左表对象是否仍应出现在结果中。

示例

示例数据表

表名:orders
orders
idcustomer_id
1 101
2 102
3 101
4 104
表名:customers
customers
idname
101 Alice
102 Bob
103 Cindy

优化前 / 不推荐

SELECT o.id, c.name FROM orders o LEFT JOIN customers c ON o.customer_id = c.id WHERE c.name = 'Alice' ORDER BY o.id;

优化前运行结果

result
idname
1 Alice
3 Alice

优化后 / 推荐

SELECT o.id, c.name FROM orders o LEFT JOIN customers c ON o.customer_id = c.id AND c.name = 'Alice' ORDER BY o.id;

优化后运行结果

result
idname
1 Alice
2 NULL
3 Alice
4 NULL

为什么这样更好:WHERE 删除右表未匹配行;把条件放进 ON 只限制匹配,同时保留全部订单。

这篇内容是否清楚?