MySQL 中 IN
适合查离散值,不是范围
当你要匹配几个明确的、不连续的值(比如用户 ID 是 101、205、318),
IN最直接:
SELECT * FROM users WHERE id IN (101, 205, 318);它底层会转成多个
=条件用
OR连接。但千万别用
IN查范围——比如写
id IN (1,2,3,...,1000),不仅写起来累,MySQL 优化器也难走索引,性能会断崖式下跌。
BETWEEN
只能查闭区间,且对类型敏感
BETWEEN a AND b等价于
col >= a AND col ,两端都包含。注意三点:如果字段是
DATETIME,而你写
BETWEEN '2024-01-01' AND '2024-01-31',实际查的是
'2024-01-01 00:00:00'到
'2024-01-31 00:00:00',会漏掉当天其他时间的数据 字符串比较按字典序,
WHERE name BETWEEN 'A' AND 'C'会包含
'Bbb',但不包含
'Ca'(因为
'Ca' > 'C')
BETWEEN不能用于
NULL判断——
col BETWEEN NULL AND 10永远为
FALSE
范围查询优先用 >=
和 替代 <code>BETWEEN
尤其处理时间范围时,显式写边界更可控:
SELECT * FROM orders WHERE created_at >= '2024-01-01' AND created_at < '2024-02-01';这样能精准覆盖整个月,且 MySQL 更容易利用索引(
比 <code> 在某些索引扫描场景下更友好)。对数字主键分页也同理:<code>id >= 1000 AND id 比 <code>id BETWEEN 1000 AND 1999逻辑更清晰,也避免了
BETWEEN在大值溢出时的隐式转换风险。
集合 + 范围混合查询要拆开写,别硬塞进一个条件
比如“查状态是
'paid'或
'shipped',且创建时间在最近 7 天内”,不能写成:
WHERE status IN ('paid', 'shipped') AND created_at BETWEEN ...这没问题;但如果你还想要“ID 在某个列表里,或者时间在某范围内”,就别强行合并:WHERE id IN (1,2,3) OR created_at >= '...'——这种
OR很可能让索引失效。更稳的做法是用
UNION ALL分开查再合并,尤其当两部分数据量差异大时,优化器更容易各自选对索引。
实际写的时候,
IN列表超过几百项就要警惕内存和执行计划退化;
BETWEEN看似简单,但时间字段的隐式截断和字符集排序规则才是最容易翻车的地方。
