between and 是闭区间操作符,左右边界均包含;若字段为 date 类型,则 between '2024-01-01' and '2024-01-31' 覆盖整月;若为 datetime/timestamp 类型,需写成 between '2024-01-01' and '2024-01-31 23:59:59' 才覆盖全天。

WHERE子句中用BETWEEN AND写日期范围时,边界值是否包含?
BETWEEN AND 是闭区间操作符,左右边界都包含。比如 date_column BETWEEN '2024-01-01' AND '2024-01-31' 会匹配到 '2024-01-01 00:00:00' 和 '2024-01-31 00:00:00',但不会包含 '2024-01-31 14:22:05'——因为默认时间部分为 00:00:00,实际比较的是完整 datetime 值。
- 如果字段是
DATE类型(无时间),BETWEEN '2024-01-01' AND '2024-01-31'安全覆盖整月 - 如果字段是
DATETIME或TIMESTAMP,且你想覆盖“整个1月31日”,得写成BETWEEN '2024-01-01' AND '2024-01-31 23:59:59'或更好:用+ <code> 组合 - MySQL 8.0+、PostgreSQL、SQL Server 都遵循这一语义;SQLite 的
DATE()函数需额外注意隐式转换
日期字符串格式不匹配导致BETWEEN失效的常见原因
数据库对字符串字面量的解析依赖格式和系统设置。直接写 '2024/01/01' 或 '01-01-2024' 在某些方言里可能被当作无效日期或转成错误值(如 MySQL 的 '0000-00-00')。
- 始终使用标准 ISO 格式:
'YYYY-MM-DD'(日期)或'YYYY-MM-DD HH:MM:SS'(时间戳) - 避免依赖
CONVERT或STR_TO_DATE做运行时转换——性能差,且容易因 NLS 设置失败 - PostgreSQL 对格式更严格,
'2024-01-01'::date显式类型转换比隐式更可靠 - SQL Server 中若列是
datetime2,而字符串没带毫秒,仍能匹配;但用datetime类型时,精度截断可能导致边界偏差
用BETWEEN AND替代>= AND
语法等价,执行计划通常完全一致——优化器会把 BETWEEN a AND b 重写为 col >= a AND col 。但可读性上 <code>BETWEEN 更紧凑,尤其多条件嵌套时。
- 不要为了“看起来快”而强行用
BETWEEN:它不支持非对称边界(比如想查>= start AND 就不能用) - 当需要开区间(如排除结束日),硬套
BETWEEN反而易错:BETWEEN '2024-01-01' AND '2024-01-30 23:59:59'不如date_col >= '2024-01-01' AND date_col - 索引有效性取决于字段是否为前导列、是否 SARGable——
BETWEEN不影响这点,但函数包装列(如DATE(created_at) BETWEEN ...)会失索引
跨时区场景下BETWEEN AND容易忽略的关键点
如果你的数据库服务器、应用连接、字段存储时区不统一,BETWEEN 看似在筛“某天”,实际可能漏掉或重复数据。
- PostgreSQL 的
timestamptz列存的是 UTC,查询时传入的字符串会被按 client timezone 解析——BETWEEN '2024-01-01' AND '2024-01-31'实际查的是客户端时区下的 UTC 范围 - MySQL 的
TIMESTAMP自动转 UTC 存储,但datetime不转——混用时BETWEEN行为不一致 - 安全做法:统一用 UTC 字符串查询,或显式转换:
created_at AT TIME ZONE 'UTC' BETWEEN ...(PostgreSQL)
BETWEEN 后,务必用 EXPLAIN 看是否走索引,并用 SELECT MIN(col), MAX(col) 实际验证边界值是否如你所想。











