between and是闭区间,左右边界均包含;但datetime/timestamp类型下'2024-01-31'隐式转为'2024-01-31 00:00:00',会遗漏当日后续时间,应显式写'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'(除非字段类型是DATE且无时间部分)。常见错误是以为它自动覆盖整天,结果漏掉当天下午的数据:
- 字段是
DATETIME或TIMESTAMP类型时,'2024-01-31'会被隐式转成'2024-01-31 00:00:00',导致 1 月 31 日 00:01 之后的数据全被排除- 正确做法是显式写终点为
'2024-01-31 23:59:59',或更稳妥地用+ <code> 组合MySQL和PostgreSQL对字符串日期的隐式转换行为不同
写
BETWEEN '2024-01-01' AND '2024-01-31'看似简洁,但实际执行依赖数据库如何解析字符串。MySQL 通常能宽松转换,PostgreSQL 则更严格,可能报错ERROR: invalid input syntax for type date。建议统一显式转换:
- MySQL:用
STR_TO_DATE('2024-01-01', '%Y-%m-%d')或直接传DATE字面量(如DATE '2024-01-01',MySQL 8.0+ 支持)- PostgreSQL:必须用
DATE '2024-01-01'或'2024-01-01'::DATE- SQL Server:推荐
CONVERT(DATE, '2024-01-01'),避免受语言/区域设置影响用
BETWEEN AND查“最近7天”容易出错的三个点动态日期范围是高频需求,但直接套
BETWEEN DATE_SUB(CURDATE(), INTERVAL 6 DAY) AND CURDATE()有隐患:
- 如果字段含时间(如
DATETIME),CURDATE()返回的是'2024-04-05'(即'2024-04-05 00:00:00'),终点只覆盖到当天零点,丢掉所有非零点数据DATE_SUB(CURDATE(), INTERVAL 6 DAY)算出来是 3 月 30 日,但“最近 7 天”应是 3 月 30 日 00:00 到 4 月 5 日 23:59:59 —— 这里天数计算逻辑易混淆- 跨月时(如从 4 月 1 日倒推 6 天),某些旧版 MySQL 在
DATE_SUB中处理月末边界不一致,建议用ADDDATE(CURDATE(), INTERVAL -6 DAY)替代比
BETWEEN AND更安全的日期范围写法多数场景下,显式用两个比较符反而更可控、可读性更强,也规避了
BETWEEN对时间精度的模糊性:WHERE date_column >= '2024-01-01' AND date_column <p>这种写法的好处:</p>
- 右边界用
而不是 <code>,天然覆盖整个月(只要 <code>'2024-02-01'是精确到日的起点)- 索引友好:大多数数据库对
>=+组合能有效走范围索引,而 <code>BETWEEN在某些执行计划里可能被重写为等价形式,但不保证- 时区安全:若字段是
TIMESTAMP,且应用层与数据库时区不一致,显式写法更容易对齐预期时间点真正要注意的从来不是语法能不能写,而是字段类型、存储精度、时区设置这三项——它们共同决定一行记录到底算不算“在范围内”。











