mysql多条件where需逻辑清晰、括号明确、索引可用;and优先级高于or,混用必加括号;in替代多or更安全高效;not in/not between易致索引失效,应避免。

MySQL里用 WHERE 组合多个条件,核心就三点:逻辑清晰、括号明确、索引可用。不加括号靠默认优先级,很容易查出意料之外的结果;不考虑索引,再对的SQL也可能慢得没法用。
AND 和 OR 混用时必须加括号
MySQL 中 AND 优先级高于 OR,但人脑记不住、也别指望别人读代码时能还原你的“本意”。比如这句:
SELECT * FROM orders WHERE status = 'shipped' OR user_id = 123 AND amount > 1000
它实际等价于:
SELECT * FROM orders WHERE status = 'shipped' OR (user_id = 123 AND amount > 1000)
——如果你本意是“用户123的所有大额订单”或“所有已发货订单”,那结果就错了。正确写法是:
-
WHERE (status = 'shipped') AND (user_id = 123)→ 查指定用户的已发货单 -
WHERE status = 'shipped' OR (user_id = 123 AND amount > 1000)→ 明确表达混合逻辑 - 哪怕只有一处
OR,只要和AND共存,就全用括号包住子条件
IN 替代一长串 OR 更安全也更高效
写 WHERE type = 'A' OR type = 'B' OR type = 'C' 不仅啰嗦,还容易漏掉条件、拼错值。换成 IN 更简洁,也更利于优化器走索引(尤其当字段有索引时):
-
WHERE type IN ('A', 'B', 'C')等价于上面三个OR,但可读性和维护性高得多 -
IN里的值数量不宜过多(比如超过几百个),否则可能触发 MySQL 的max_allowed_packet限制或导致执行计划退化 - 注意:
IN对NULL值不敏感 ——WHERE col IN (1, 2, NULL)不会匹配col IS NULL,要单独写OR col IS NULL
NOT 配合 IN 或 BETWEEN 时小心索引失效
NOT IN 和 NOT BETWEEN 在大多数情况下无法使用索引(除非是覆盖索引+极小数据集),性能风险很高:
-
WHERE id NOT IN (1, 2, 3)→ 即使id有主键索引,MySQL 仍可能全表扫描 - 更稳妥的替代:用
LEFT JOIN ... IS NULL或改写为WHERE id 3(仅适用于连续范围) -
WHERE created_at NOT BETWEEN '2025-01-01' AND '2025-12-31'→ 建议拆成created_at '2025-12-31',便于索引利用
真正难的不是写出语法正确的组合条件,而是判断哪些条件能走索引、哪些会让查询变慢,以及当 EXPLAIN 显示 type: ALL 时,你得立刻意识到括号没加对,或者 NOT 把索引废掉了。











