MySQL 中 ON 条件与 WHERE 过滤的执行顺序解析
在 SQL 开发中,初学者常混淆 `JOIN` 连接的 `ON` 条件与后续 `WHERE` 过滤的执行时机。核心结论是:对于 `LEFT JOIN`,`ON` 子句中的额外条件仅作为“连接过滤器”,不破坏左表的完整性;而 `WHERE` 子句作为“最终结果过滤器”,会在连接完成后对所有行生效,可能使左表特有的 NULL 行因条件不符而被剔除。
JOIN 连接类型简述
在进行深度对比前,需明确三种常用连接方式的语义:
INNER JOIN(内连接):仅返回两个表中匹配成功的记录。LEFT JOIN(左连接):返回左表的所有记录。若右表无匹配项,右表字段填充为NULL。RIGHT JOIN(右连接):与左连接相反,保证右表所有记录输出,左表无匹配时填NULL。
准备测试环境
为了直观展示差异,我们构建两张关联表 a1 和 a2。二者通过数值字段 y 进行关联。
create table if not exists `a1`(
`x` int(10),
`y` int(10)
);
create table if not exists `a2`(
`y` int(10),
`z` int(10)
);
测试数据如下:
表 a1:
| x | y |
|---|---|
| 1 | 10 |
| 2 | 20 |
| 3 | 30 |
表 a2:
| y | z |
|---|---|
| 10 | 100 |
| 20 | 200 |
| 20 | 300 |
ON 条件与 WHERE 的执行差异
我们将针对 LEFT JOIN 场景,对比将筛选逻辑放在 ON 关键字后与放在语句末尾 WHERE 的不同表现。
第1步:标准 LEFT JOIN(基线测试)
首先执行不带额外条件的连接,观察原始关联结果:
select * from a1 left join a2 on a1.y = a2.y;
执行结果集:
| a1.x | a1.y | a2.y | a2.z |
|---|---|---|---|
| 1 | 10 | 10 | 100 |
| 2 | 20 | 20 | 200 |
| 2 | 20 | 20 | 300 |
| 3 | 30 | NULL | NULL |
分析:由于左表 a1 中 x=3 的行在右表无对应数据,因此其右侧字段显示为 NULL,但该行依然存在于结果集中。
第2步:ON 条件附加过滤 (AND)
在 ON 子句中增加限制条件,只允许 a2.y = 10 的记录参与匹配:
select * from a1 left join a2 on a1.y = a2.y and a2.y = 10;
执行结果集:
| a1.x | a1.y | a2.y | a2.z |
|---|---|---|---|
| 1 | 10 | 10 | 100 |
| 2 | 20 | NULL | NULL |
| 3 | 30 | NULL | NULL |
关键点:尽管 x=2 的行在右表原本有匹配,但因为加了 a2.y=10 的限制导致匹配失败,其右侧变为了 NULL。然而,左表的这三行全部被保留了下来。
这证明了 ON (Condition) 实际上是作用在右表查找过程中的。它的逻辑相当于先根据复合条件生成一个虚拟中间表,再与左表做自然连接。
第3步:WHERE 全局过滤
将相同的限制条件移至连接完成后的 WHERE 子句:
select * from a1 left join a2 on a1.y = a2.y where a2.y = 10;
执行结果集:
| a1.x | a1.y | a2.y | a2.z |
|---|---|---|---|
| 1 | 10 | 10 | 100 |
分析:此时仅剩一条记录。因为 WHERE 是在连接操作完成后执行的。在第 2 步的结果中,x=2 和 x=3 对应的 a2.y 值为 NULL,显然不满足 WHERE a2.y = 10 的条件,从而被彻底过滤掉。
总结
MySQL 执行逻辑模型:
ON ... AND condition:作为连接的一部分,决定左右表如何拼合。它不会减少左表的行数,只会让符合条件的右边行匹配成功,不符合的右边行补NULL。... WHERE condition:作为最终筛选器,作用于整个 Join 产生的临时结果集。它会过滤掉整行数据,包括那些左表原本存在但因 Right/Outer Join 产生 NULL 值的行。
简而言之:ON 管的是“连不连得上”,WHERE 管的是“留不留得下”。
以上就是 MySQL 中 JOIN 的 ON 条件与 WHERE 过滤详细解析,更多关于 MySQL 进阶优化的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













