广告设计网站官网北京小程序定制开发
写联表查询SQL时筛选条件写在where 前面和后面有啥区别
ON 条件作用于「表连接阶段」,WHERE 条件作用于「连接完成后的结果集过滤阶段」,二者在逻辑执行顺序、对连接结果的影响上完全不同
一、先明确你的 SQL 中「条件的当前位置」
你的 SQL 里存在两类筛选条件,先对应到「ON 前 / 后」的概念:
| 条件位置 | 具体条件 | 作用阶段 |
|---|---|---|
| JOIN 的 ON 子句中 | rel.id = ord.bidding_indicator_release_id(连接条件)、ord.del_flag = 'N'、cate.review_status != 'shbh' | 表连接阶段 |
| WHERE 子句中 | rel.del_flag = 'N'、rel.release_status = 'yjcj' | 连接后结果集过滤 |
下面通过「把 ON 中的条件移到 WHERE 后」和「把 WHERE 中的条件移到 ON 中」的对比,说明核心差异。
二、核心区别:作用阶段与对连接结果的影响
1. 对「左连接(LEFT JOIN)」的影响(最关键!)
你的 SQL 用了 LEFT JOIN(左表是 bidding_indicator_release_info rel,右表是 ord 和 cate)。左连接的核心规则是:左表的所有记录都会保留,右表只保留满足 ON 条件的记录;右表不满足条件的记录,字段值会填充为 NULL。
这时候,「条件写在 ON 还是 WHERE」会直接决定右表记录是否保留,甚至影响左表记录的最终结果:
案例 1:ord.del_flag = 'N' 写在 ON 中 vs 写在 WHERE 中
写在 ON 中(当前写法):
左连接时,只匹配ord表中del_flag = 'N'的记录。如果rel表某条记录没有对应的ord记录(或ord记录del_flag = 'Y'),ord相关字段(如user_id、price)会填充为 NULL,但rel表的这条记录会保留。移到 WHERE 中:
左连接先保留rel的所有记录(包括没有对应ord的记录),连接完成后,再用WHERE ord.del_flag = 'N'过滤结果集。
但此时,rel表中没有对应ord的记录,ord.del_flag是 NULL,而NULL = 'N'不成立,所以 这些rel记录会被过滤掉,最终效果等同于「内连接(INNER JOIN)」,左表的 “左连接特性” 失效。
案例 2:cate.review_status != 'shbh' 写在 ON 中 vs 写在 WHERE 中
同理,cate 是通过 LEFT JOIN 关联到 ord 的:
写在 ON 中:
只匹配cate表中review_status != 'shbh'的记录。如果ord没有对应cate记录(或cate的review_status = 'shbh'),cate相关字段(ship_info_id、ship_name)会填充为 NULL,但rel和ord的记录会保留。移到 WHERE 中:
连接完成后过滤cate.review_status != 'shbh',此时cate字段为 NULL 的记录(无对应cate或review_status = 'shbh')会被过滤,导致rel和ord的记录也被删除,破坏左连接逻辑。
2. 对「内连接(INNER JOIN)」的影响(差异较小)
如果你的 SQL 是 INNER JOIN(只保留左右表都匹配的记录),那么「条件写在 ON 还是 WHERE」最终结果可能相同,但逻辑执行顺序不同:
ON条件:先过滤右表,再和左表做内连接(减少连接的数据量,效率可能更高);WHERE条件:先做内连接(保留所有匹配记录),再过滤结果集(连接的数据量更大,效率可能更低)。
但你的 SQL 是 LEFT JOIN,所以内连接的场景不适用,核心差异还是集中在左连接的记录保留逻辑上。
3. 对「左表(rel)的过滤条件」的影响
你的 WHERE 中有 rel.del_flag = 'N' 和 rel.release_status = 'yjcj',这些是对左表 rel 的过滤条件。如果把它们移到 LEFT JOIN rel ON ... 中(假设 rel 是其他表的右表,但你的 SQL 中 rel 是主表,没有左表):
- 若
rel是主表(FROM 后的表),过滤条件只能写在WHERE中(因为主表没有 ON 条件); - 若
rel是被连接的右表(如A LEFT JOIN rel ON ...),则rel.del_flag = 'N'写在 ON 中,会保留 A 表所有记录,只匹配 rel 满足条件的记录;写在 WHERE 中,会过滤掉 A 表中没有匹配 rel 或 rel 不满足条件的记录,等同于内连接。
三、总结:你的 SQL 中条件位置的「正确与否」
结合业务需求(通常左连接是为了保留主表 rel 的所有有效记录,同时关联右表的匹配数据),你的 SQL 中条件位置大部分合理,但有一个细节需要注意:
| 条件 | 当前位置 | 是否合理? |
|---|---|---|
rel.id = ord.id | ON | 合理:连接条件必须写在 ON 中,否则无法关联两表。 |
ord.del_flag = 'N' | ON | 合理:保留 rel 所有有效记录,只关联 ord 未删除的记录(无效 ord 显示 NULL)。 |
cate.review_status!='shbh' | ON | 合理:保留 ord 记录,只关联 cate 未被驳回的记录(无效 cate 显示 NULL)。 |
rel.del_flag = 'N' | WHERE | 合理:过滤主表 rel 未删除的记录(主表过滤只能写在 WHERE)。 |
rel.release_status='yjcj' | WHERE | 合理:过滤主表 rel 已竞价成交的记录(主表过滤只能写在 WHERE)。 |
四、关键口诀
判断条件写在 ON 还是 WHERE,记住这 2 条:
- 连接条件(如 A.id = B.a_id)必须写在 ON 中,否则无法建立表关联;
- 左连接中,想保留左表所有记录 → 右表的过滤条件写在 ON 中;想过滤掉左表中无右表匹配的记录 → 右表的过滤条件写在 WHERE 中(等同于内连接);
- 主表(FROM 后的表)的过滤条件,只能写在 WHERE 中(主表没有 ON 条件,写在 ON 中无效)。
