BETWEEN AND 在SQL中确实包含边界值,但查不到当天晚上记录的主因是日期字符串隐式转为当日00:00:00,导致右边界截断;应改用 >= AND < 半开区间,如 created_at >= '2024-05-01' AND created_at < '2024-05-11'。

BETWEEN AND 在标准 SQL 和主流数据库(MySQL、PostgreSQL、SQL Server、Oracle)中一定包含边界值,即等价于 column >= value1 AND column <= value2。
但实际使用中,是否“看起来包含”,往往取决于数据类型和值本身的精度,尤其是日期时间字段。
为什么查不到当天晚上的记录?——日期字段的隐式截断问题
常见现象:WHERE order_date BETWEEN '2023-01-01' AND '2023-12-31' 查不到 '2023-12-31 14:25:33' 这样的记录。
原因不是 BETWEEN 不包含边界,而是字符串 '2023-12-31' 被数据库隐式转为 '2023-12-31 00:00:00'(具体行为依数据库而异),导致 '2023-12-31 14:25:33' > '2023-12-31 00:00:00',但不满足 '2023-12-31 00:00:00'。
- MySQL / PostgreSQL:会将
'2023-12-31'解释为'2023-12-31 00:00:00' - SQL Server:同上,且严格按 datetime 类型精度对齐
- Oracle:类似,但对
DATE类型默认时间部分为 00:00:00
✅ 正确写法(推荐):WHERE order_date >= '2023-01-01' AND order_date —— 避免边界模糊,语义清晰,也利于索引使用。
数值和字符串场景下,边界包含性是确定的
BETWEEN 对数字和字符串的行为稳定且可预测,只要值本身无歧义:
-
amount BETWEEN 100 AND 500包含100和500(等价于amount >= 100 AND amount ) -
name BETWEEN 'alice' AND 'bob'按字典序比较,包含所有以'alice'开头或等于'bob'的值(注意:若列含尾随空格或大小写敏感 collation,结果可能出乎意料) - 若
value1 > value2(如BETWEEN 100 AND 50),多数数据库返回空结果集,不报错但逻辑失效
NOT BETWEEN 的边界逻辑同样闭合
NOT BETWEEN 10 AND 20 等价于 column 20,即排除闭区间 [10, 20] 内所有值,包括 10 和 20。
⚠️ 注意:它**不是** column = 20 —— 那样会漏掉 10 的中间部分。
所以 NOT BETWEEN 的“否定”是针对整个闭区间,不是对每个比较符取反。
索引能用上吗?关键看列和写法
BETWEEN 查询在有合适索引时通常能走范围扫描(range scan),但以下情况会失效:
- 对列做了函数操作,如
WHERE YEAR(created_at) BETWEEN 2023 AND 2025—— 索引失效 - 字符列未加前缀索引或 collation 不匹配,导致字符串
BETWEEN无法高效定位 - 边界值为
NULL:如status BETWEEN NULL AND 'active'结果不可靠,因为任何与NULL的比较都为UNKNOWN
✅ 建议:用于 BETWEEN 的列应单独建索引;日期范围优先用 >= + 组合,更可控、更易优化。
真正容易被忽略的,是日期字段的时间部分处理方式 —— 它不改变 BETWEEN 本身的闭区间语义,却让“包含边界”在业务上失效。别怪语法,要查数据精度和隐式转换规则。

















