首页/数据/数据库速查/WHERE 条件过滤与运算符
SQL 语法52 条

WHERE 条件过滤与运算符

用比较、逻辑、范围与空值运算符筛选行;NULL 判断必须用 IS NULL,任何与 NULL 的比较结果都是未知。

数据库速查数据更新于 2026-10-13

WHERE 是什么

WHERE 是行级过滤子句,在 FROM 完成取数与连接之后、分组之前对原始行做筛选,也是决定索引能不能被用上的关键位置。它最容易出错的地方是空值:NULL 表示未知,任何与 NULL 的比较结果都是未知而不是假,所以判空只能写 IS NULL、IS NOT NULL,NOT IN 的子查询里一旦出现 NULL,整条判断都会失去意义。理解这一点,大部分「条件看起来对却查不到数据」的问题就有答案了。

基本信息

用途行级过滤,直接决定扫描范围
语法WHERE 条件 [AND|OR 条件] ...
比较运算符= <> != < <= > >=、BETWEEN、IN、LIKE、IS NULL
逻辑优先级NOT 高于 AND,AND 高于 OR,混用必须加括号
索引要点条件要作用在索引列本身,不要套函数或做运算
执行位置FROM 之后、GROUP BY 之前,不能引用 SELECT 的别名

典型使用场景

  • 列表接口按状态、时间范围、用户过滤,条件写法直接决定是否走索引
  • 数据核查:按单号或用户定位记录,用等值条件精确命中
  • 增量同步与归档:用时间范围圈出当天或某一批次的数据
  • 排查查不到数据:确认是判空写错、隐式类型转换,还是条件本身不成立
  • 模糊搜索按前缀匹配,把通配符放在字符串末尾才能用上索引
  • 多条件组合筛选,注意 AND 与 OR 混用时的括号与优先级

条件示例

条件示例
SELECT id, status, amount FROM orders WHERE status = 'paid';   # 等值条件,走索引的首选
SELECT id FROM orders WHERE qty BETWEEN 1 AND 10 AND amount > 100;   # 范围加比较,范围列尽量靠后
SELECT id FROM orders WHERE user_id IN (1001, 1002, 1003);   # 集合条件,短列表等价多次等值
SELECT id FROM orders WHERE remark IS NULL;   # 判空只能用 IS NULL,= NULL 永远查不到
SELECT id FROM orders WHERE sku LIKE 'A100%';   # 前缀模糊可用索引
SELECT id FROM orders WHERE status='paid' AND (channel='web' OR channel='app');   # 逻辑混用加括号

运算符与索引影响

写法含义对索引的影响
=等值匹配,最理想的条件可直接定位索引记录
BETWEEN a AND b闭区间范围可用索引,其后的复合列不再失效但利用率下降
IN (...)命中集合内任一值短列表走索引,超长列表退化为扫描
LIKE 'abc%'前缀匹配可使用索引
LIKE '%abc%'两端通配无法用 B 树索引,需全文检索方案
IS NULL / IS NOT NULL空值判断与列的允许空性和统计信息有关
!= 或 NOT IN取反条件优化器常放弃索引转为扫描
列做运算或套函数条件不在索引列本身索引失效

反例与改写

反例与改写
# 反例:函数包住索引列,索引失效
SELECT id FROM orders WHERE DATE(created_at) = '2026-10-12';
# 改写:改范围条件,索引可用
SELECT id FROM orders
WHERE created_at >= '2026-10-12' AND created_at < '2026-10-13';
# 反例:NOT IN 的子查询可能返回 NULL
SELECT id FROM orders WHERE user_id NOT IN (SELECT user_id FROM blacklist);
# 改写:用 NOT EXISTS 表达同样语义
SELECT o.id FROM orders o
WHERE NOT EXISTS (SELECT 1 FROM blacklist b WHERE b.user_id = o.user_id);
LIKE 只有前缀匹配能利用 B 树索引;需要任意位置模糊匹配时应评估全文索引或外部检索方案,不要在业务表上直接用两端通配的写法硬扛。
OR 条件常让优化器放弃索引,改成 IN 或拆成 UNION ALL 往往能让索引重新生效;条件值的类型与列定义不一致触发隐式转换时,索引同样会失效。
删除或更新之前,用完全相同的 WHERE 条件先做一次 SELECT 计数:条件写错的后果会从查不到数据升级成误删误改,写操作几乎无法回退。

条件写法检查清单

  • 等值条件优先于范围与模糊:等值可直接定位到索引位置,代价最低
  • 复合索引上范围条件之后的列不再参与定位,把等值列放在范围列之前
  • 判空条件与其他条件用 OR 连接时容易让索引失效,可拆成两条查询再合并结果
  • 最具选择性的条件写在前面对可读性有帮助,但真正决定索引的是优化器与统计信息
  • 上线前用 EXPLAIN 复核:确认访问类型与使用的索引和预期一致
  • 条件里出现的列都写在同一张表上,避免在过滤条件中做跨表关联
索引列上的 IS NULL 也能使用索引,但空值比例高时优化器可能判断走全表更划算,这类查询要单独用 EXPLAIN 验证,而不是照搬等值条件的经验。

易错点

  • 用 = NULL 或 <> NULL 判空:与 NULL 的比较结果恒为未知,条件永远不成立,必须改成 IS NULL / IS NOT NULL
  • NOT IN 的子查询结果里含 NULL:整体判断变成未知,一行都匹配不上,应改用 NOT EXISTS 或先剔除 NULL
  • 对索引列套函数或做算术:索引失效退化为全表扫描,改成范围条件或预先计算好值
  • AND 与 OR 混用不加括号:实际语义与预期不符,查数据时结果错,用于写操作时后果更严重
  • 条件值类型与列定义不一致:隐式转换让索引失效,还可能匹配到本不该命中的行

数据来源与参考

  • MySQL 8.0 Reference Manual: SELECT Statement - WHERE Clause

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌