SQL 多表查询实用技巧:ON 和 WHERE 的区别速览
在 SQL 面试和实际开发中,多表查询是绕不过去的重点。尤其是 ON 和 WHERE 的区别,很多初学者常常混淆,结果写出的语句逻辑错误,甚至导致数据结果不一致。本文带你快速理清这两者的区别和应用场景,避免踩坑。
一、基础概念回顾
在多表查询中,常见的写法有两种:
1. 在 JOIN ... ON 中写条件
用于指定两张表之间的连接关系,比如主外键的对应。
2. 在 WHERE 中写条件
用于对最终结果集再进行筛选,类似于过滤器。
简单来说,ON 是连接条件,WHERE 是结果集过滤条件。
二、ON 与 WHERE 的差异
1. INNER JOIN 中差异不大
当使用 INNER JOIN 时,无论把条件写在 ON 还是 WHERE 中,结果基本一致。因为内连接本身就是取两表交集部分。
示例:
-- 条件写在 ON
SELECT s.id, s.name, c.course_name
FROM Student s
INNER JOIN Course c ON s.id = c.student_id;
-- 条件写在 WHERE
SELECT s.id, s.name, c.course_name
FROM Student s
INNER JOIN Course c
WHERE s.id = c.student_id;
两者的结果相同。
2. OUTER JOIN 中差异显著
在 LEFT JOIN 或 RIGHT JOIN 中,ON 和 WHERE 的位置不同,结果可能差别很大。
● 条件写在 ON 中
保证了外连接的特性,比如 LEFT JOIN 会保留左表全部数据,即使右表没有匹配记录。
● 条件写在 WHERE 中
会对结果集进行二次过滤,可能导致外连接退化为内连接。
示例:
-- 条件写在 ON 中(会保留所有学生,即使没有课程)
SELECT s.id, s.name, c.course_name
FROM Student s
LEFT JOIN Course c ON s.id = c.student_id;
-- 条件写在 WHERE 中(只保留有课程的学生,左连接失效)
SELECT s.id, s.name, c.course_name
FROM Student s
LEFT JOIN Course c ON s.id = c.student_id
WHERE c.course_name IS NOT NULL;
第一条语句会保留所有学生;第二条语句会丢掉没有课程的学生,等同于 INNER JOIN。
三、常见面试陷阱
1. 问:为什么 LEFT JOIN 还写了 WHERE c.col IS NOT NULL,结果和 INNER JOIN 一样?
因为 WHERE 把空值过滤掉了,丢掉了外连接的“补全”功能。
2. 问:实际项目里该怎么写?
连接条件写在 ON,过滤条件写在 WHERE,语义清晰,不容易混淆。
3. 问:能否通过 ON 写过滤条件?
可以,但要谨慎。比如 ON c.status = 'active',这意味着只在连接时考虑满足条件的行,不会再保留其他结果。
四、最佳实践总结
ON:定义两表之间的连接关系。
WHERE:在结果集上再做过滤。
INNER JOIN:两者差别不大。
OUTER JOIN:差别显著,容易出错,必须小心。
一句口诀:
“连接写在 ON,过滤放 WHERE,OUTER JOIN 特别注意不要混用。”
五、结语
多表查询是 SQL 的高频考点,也是开发常见的操作。真正理解 ON 和 WHERE 的区别,不仅能避免逻辑 bug,还能在面试中体现你对 SQL 细节的掌握。