根本原因是AND优先级高于OR,不加括号会导致逻辑错误;必须用括号明确分组,如(status='active' OR status='pending') AND (payment_method IN ('alipay','wechat')),NOT后复合条件也须括号包裹。

WHERE子句里混用AND和OR时,为什么结果总不对?
根本原因是运算符优先级:SQL中AND永远比OR先执行,不管书写顺序。不加括号就相当于给所有AND条件自动套了隐式小括号,OR被“挤”到最外层。
比如写WHERE status = 'active' OR role = 'admin' AND dept = 'tech',实际等价于WHERE status = 'active' OR (role = 'admin' AND dept = 'tech'),而不是你直觉想表达的“是活跃用户或者管理员,并且部门是tech”。
- 只要出现
AND和OR共存,无条件加括号——哪怕只有一处OR - 把语义上属于同一组的条件用
()明确圈起来,比如(status = 'active' OR status = 'pending') - 避免写
WHERE a = 1 OR b = 2 AND c = 3这种裸写法,它极易引发误读和线上bug
需要同时满足多组“或关系”的场景,怎么写才安全?
典型例子:查“订单状态是已发货或已完成,且支付方式是支付宝或微信”。这里有两个独立的“或”逻辑,必须各自包裹,再用AND连接。
正确写法:WHERE (status = 'shipped' OR status = 'completed') AND (payment_method = 'alipay' OR payment_method = 'wechat')
- 每个
OR组合单独加括号,不省略 - 不要试图靠空格或缩进暗示逻辑分组——SQL解析器完全不认这个
- 如果括号太多看着晕,可考虑用
IN简化,比如status IN ('shipped', 'completed')语义更清晰,也更易维护
NOT和AND/OR一起用,最容易漏掉哪层括号?
NOT作用范围默认只覆盖紧挨着它的下一个表达式,不是整条条件。写WHERE NOT a = 1 OR b = 2,实际是(NOT a = 1) OR b = 2,而非NOT (a = 1 OR b = 2)。
- 只要
NOT后面跟着复合条件(含AND/OR),就必须手动加括号包住整个被否定的部分 - 否定“多条件同时成立”,要写
NOT (a = 1 AND b = 2);否定“任一条件成立”,要写NOT (a = 1 OR b = 2) - 用
!=或<>替代NOT column = value仅适用于单值比较,对NULL或复杂表达式无效,别偷懒
在JOIN或子查询里嵌套多重条件,括号还重要吗?
一样重要,而且更容易出错。因为ON子句、子查询的WHERE、甚至HAVING都遵循完全相同的优先级规则。
例如左连接中想保留所有用户,但只关联“状态有效且非测试账号”的订单:LEFT JOIN orders ON users.id = orders.user_id AND (orders.status = 'valid' AND orders.is_test = 0)——这里的括号确保两个订单条件是“同时满足”,否则AND orders.is_test = 0可能意外变成过滤主表的条件。
-
ON里的逻辑组合,括号不能省;WHERE里对主表的筛选和对关联表的筛选也要区分清楚 - 子查询内部若含
OR,必须自包含括号,外部调用时不会帮你“继承”逻辑层级 - 用EXPLAIN看执行计划时,如果发现本该走索引的字段没被用上,大概率是括号缺失导致优化器误判了条件组合方式
(),可能让查询结果偏差几个数量级,而数据库不会报错,只会安静地返回错的数据。

















