多条件组合筛选需规范使用括号、避免NULL陷阱、慎用IN/NOT IN、子查询承载逻辑、警惕函数致索引失效。

多条件组合筛选不是堆AND/OR就能成事,括号漏写、NULL混入、函数滥用,三条里踩中一条,结果就离谱。
WHERE里AND和OR混用必须加括号
数据库按 AND 优先于 OR 执行,不加括号时 WHERE a = 1 OR b = 2 AND c = 3 等价于 WHERE a = 1 OR (b = 2 AND c = 3),而不是你直觉里的 (a = 1 OR b = 2) AND c = 3。线上查不出数据或数据爆炸,八成是这里错了。
- 所有语义上属于同一组的
OR条件,必须用括号包住,比如WHERE (status = 'active' OR status = 'pending') AND created_at >= '2026-01-01' - 多个
AND组之间再用OR连接时,外层也建议加括号,例如WHERE (type = 'vip' AND score > 80) OR (type = 'trial' AND last_login > '2026-08-01') - 用缩进对齐括号层级,比省几个空格重要得多——下次你或同事改这条 SQL 时会谢你
IN只适合单字段多值,别硬套多条件
IN 是 = ... OR = ... 的语法糖,它只解决“这个字段是否在某几个值里”的问题。想约束多个字段同时成立(比如“国家是CN且等级≥5”),IN 无能为力,必须用 AND。
- ✅ 正确:查三个国家的用户 ——
WHERE country IN ('CN', 'US', 'JP') - ❌ 错误:查“alexa在1–10之间且country='CN'”,却写成
WHERE alexa IN (1,2,3,4,5,6,7,8,9,10) AND country IN ('CN');可读性差,且IN在这里毫无必要 - ⚠️ 隐患:如果子查询返回含
NULL的结果(如SELECT user_id FROM logs WHERE type = 'error'),整个IN条件变成UNKNOWN,结果集为空——这种 bug 很难复现,但一出就是线上事故
NULL参与比较永远返回UNKNOWN,WHERE会静默丢弃
SQL用三值逻辑,NULL = 'abc'、NULL != 5、NULL > 100 全部返回 UNKNOWN,而 WHERE 只保留 TRUE 行,UNKNOWN 等同于被过滤掉。
- 查非空邮箱不能只写
WHERE email != '',因为email IS NULL的行也被漏了;得写WHERE email IS NOT NULL AND email != '' - 想统一排除
NULL和空字符串,WHERE COALESCE(email, '') != ''更简洁 -
NOT IN是重灾区:只要右边列表里有一个NULL,整条条件恒为UNKNOWN,结果必为空;一律改用NOT EXISTS
子查询做多条件,逻辑必须沉到内层
外层 WHERE col IN (子查询) 本身不承载多条件逻辑,真正的组合筛选全靠子查询内部实现。把复杂条件塞进子查询,外层只做 ID 匹配,才是正解。
- 子查询必须只返回一列,否则报错
subquery returns more than one column - 涉及多表关联的多条件(如“VIP用户+近7天下单+金额>100”),全部写在子查询的
JOIN和WHERE里,外层只留IN或EXISTS - 嵌套超过两层?用
WITH拆开,比如先定义recent_vip_orders,再定义high_value_items,主查询只负责组合——PostgreSQL 支持,MySQL 8.0+ 也行,旧版只能临时表或重复子查询
最常被忽略的其实是执行计划:哪怕语法全对,UPPER(name) = 'ABC' 或 DATE(created_at) = '2026-09-01' 这类写法会让索引失效,大表上直接拖垮查询。动手前先 EXPLAIN 一眼,比调半天代码更省时间。

















