连接中的 ON 与 WHERE
了解谓词应放在 ON 还是 WHERE 中,以及这为何会影响结果
连接中的 ON 与 WHERE 是 CoddyKit 上的免费 SQL Interview Prep 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 SQL Interview Prep 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 SQL Interview Prep 课程共包含 4 节课。
一个谓词可以放在两个位置
当您能够写出 INNER JOIN 后,下一个面试问题会更加深入:这个条件应该放在 ON 中,还是放在 WHERE 中?
对于 INNER JOIN,答案通常是“对结果没有影响”。但一旦切换到外连接,选择就会完全改变结果。面试官之所以准确地询问这一点,是因为初级开发者常常习惯性地把所有条件都放进 WHERE。
本课会清晰地说明这条规则。
ON 的作用
ON 子句定义行如何配对。它会在构建连接时执行,决定左表中的哪一行与右表中的哪一行匹配。
您可以把 ON 理解为在回答这样一个问题:“对于这两行,它们是否属于同一组?”
SELECT c.name, o.amount
FROM customers c
JOIN orders o
ON o.customer_id = c.id; -- pairing ruleWHERE 的作用
WHERE 子句会在连接生成合并后的行之后执行。它会筛选结果集,丢弃未通过测试的行。
您可以把 WHERE 理解为在回答这样一个问题:“既然已经完成连接,我想保留其中哪些行?”
SELECT c.name, o.amount
FROM customers c
JOIN orders o ON o.customer_id = c.id
WHERE o.amount > 30; -- filter after pairing在 INNER JOIN 中,它们通常结果相同
对于 INNER JOIN,额外的筛选条件放在 ON 中还是 WHERE 中,结果都相同。下面两个查询都会只返回 Ada 的 50 美元订单和 Bob 的 99 美元订单。
由于未匹配的行本来就会被内连接丢弃,因此移动谓词并不会改变最终保留下来的行。
-- predicate in ON
SELECT c.name, o.amount FROM customers c
JOIN orders o
ON o.customer_id = c.id AND o.amount > 30;
-- predicate in WHERE -- same result here
SELECT c.name, o.amount FROM customers c
JOIN orders o ON o.customer_id = c.id
WHERE o.amount > 30;为什么规范写法仍然建议将连接键放在 ON 中
即使结果相同,约定仍然要求:将连接关系条件放在 ON 中,将业务筛选条件放在 WHERE 中。
- ON:
o.customer_id = c.id(表之间如何关联) - WHERE:
o.amount > 30(您希望得到哪些结果)
这种分离能让下一位读者以及评判您代码风格的面试官一眼看出意图。
真正重要的地方:外连接
使用 LEFT JOIN 时,这一区别会变得十分关键,因为即使没有匹配的右表行,它也会保留每一行左表数据。下面使用客户和订单进行快速预览,其中 Cleo 没有订单。
LEFT JOIN 会保留 Cleo,但她的订单列为 NULL。现在请观察 ON 和 WHERE 分别会如何影响她的结果。
SELECT c.name, o.amount
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id;
-- keeps Ada, Bob, AND Cleo (NULL amount)将筛选条件放在 ON 中:保留行
将 amount > 30 条件放在 LEFT JOIN 的ON 中,它只会影响哪些右表行能够附加进来。未匹配的左表行仍然会被保留,只是对应位置为 NULL。
Cleo 仍会保留。任何未通过测试的订单都不会附加进来,相应位置会留下 NULL。
SELECT c.name, o.amount
FROM customers c
LEFT JOIN orders o
ON o.customer_id = c.id AND o.amount > 30;
-- Ada 50, Bob 99, Cleo NULL (3 rows, Cleo kept)将筛选条件放在 WHERE 中:外连接会退化
将同一个条件移到 WHERE 中,就会筛选连接后的结果。Cleo 的行包含 amount = NULL,而 NULL > 30 不为真,因此她会被移除。
LEFT JOIN 会悄无声息地表现得像 INNER JOIN。这是面试中最著名的连接陷阱。
SELECT c.name, o.amount
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.amount > 30;
-- Ada 50, Bob 99 (Cleo GONE -> back to inner-join behavior)需要记住的规则
在面试中请清楚地陈述:
- ON 中的条件决定右表行是否附加进来;左表行会被保留。
- WHERE 中的条件筛选最终行,当它涉及可能为 NULL 的列时,可能会删除原本保留的左表行。
因此对于外连接:可选表上的谓词应放在ON 中,除非您确实想要删除未匹配的行。
在 WHERE 中筛选 NULL 的合理用法
有一种情况下,在 WHERE 中筛选外连接得到的列完全正确:这就是反连接。测试 IS NULL 可以找出没有匹配项的左表行。
这里,WHERE 会有意只保留未匹配的行,从而返回没有任何订单的客户。机制相同,但意图相反。
SELECT c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL; -- customers with no orders -> Cleo快速思维测试
在开始测验前,看到连接条件时请按下面的清单检查:
- 它是关联两张表的连接键吗?-> ON。
- 它是对必选表的筛选吗?-> WHERE 或 ON 都可以。
- 它是对可选(外部)表的筛选,并且您希望保留未匹配的行吗?-> ON。
- 您想要找出未匹配项吗?-> WHERE ... IS NULL。
快速检查
将 ON 与 WHERE 的规则应用到外连接中。
回顾:ON 与 WHERE
面试中需要掌握的要点:
- ON 控制行的配对;对于外连接,它还决定可选行是否附加,同时保留需要保留的一侧。
- WHERE 筛选已经完成连接的结果,并可能删除原本保留的行。
- 在 INNER JOIN 中,两者通常可以互换;在外连接中则不能互换。
- 外部表上的筛选条件应放在ON 中,除非您有意使用 WHERE 中的
IS NULL来执行反连接。
常见问题解答
「连接中的 ON 与 WHERE」课时是免费的吗?
是的 — 「连接中的 ON 与 WHERE」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 SQL Interview Prep 课程的其余内容,请升级到 CoddyKit PRO。 SQL Interview Prep 课程共包含 4 节课。
「连接中的 ON 与 WHERE」这节课中我会学到什么?
了解谓词应放在 ON 还是 WHERE 中,以及这为何会影响结果 你通过在浏览器中直接运行的动手代码来练习 SQL Interview Prep,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 SQL Interview Prep 需要有经验吗?
无需任何先前经验。CoddyKit 上的 SQL Interview Prep 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「连接中的 ON 与 WHERE」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 SQL Interview Prep 课中编写并运行代码吗?
能。每节 SQL Interview Prep 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- INNER JOIN 如何匹配行
- 连接中的 ON 与 WHERE
- 连接扩张与行数增加
- 连接三个或更多表