LEFT JOIN 条件写在 ON 还是 WHERE
右表条件的位置会决定未匹配的左表行是否保留。
问题与判断方法
LEFT JOIN 的 ON 先决定哪些右表记录可以匹配,未匹配时右表字段变为 NULL。之后 WHERE 再筛选完整结果;如果 WHERE 要求右表字段满足某个值,NULL 行会被删除,结果就可能接近 INNER JOIN。
需要保留左表全部记录时,把只限制右表匹配资格的条件写进 ON。确实只要存在符合条件的右表记录时,写在 WHERE 才符合语义。
判断位置不要依赖固定口诀,而要先写清楚问题:没有匹配记录的左表对象是否仍应出现在结果中。
示例
示例数据表
表名:
orders| id | customer_id |
|---|---|
| 1 | 101 |
| 2 | 102 |
| 3 | 101 |
| 4 | 104 |
表名:
customers| id | name |
|---|---|
| 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;优化前运行结果
| id | name |
|---|---|
| 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;优化后运行结果
| id | name |
|---|---|
| 1 | Alice |
| 2 | NULL |
| 3 | Alice |
| 4 | NULL |
为什么这样更好:WHERE 删除右表未匹配行;把条件放进 ON 只限制匹配,同时保留全部订单。
这篇内容是否清楚?
感谢反馈,我们会把它用于后续内容复核。