SQLPathLab
SQL 实战指南 · MySQL 8.0

日期范围、月底和时间边界

使用半开区间处理整天整月,避免遗漏小数秒并保留索引机会。

问题与判断方法

筛选整月数据时,不要把结束时间写成 23:59:59。字段可能包含毫秒或微秒,也可能受时区转换影响。更稳定的写法是 created_at >= 月初且 created_at < 下月月初。

在 WHERE 中对日期字段套 DATE_FORMAT、DATE 或 YEAR,可能让普通索引难以使用。范围条件直接作用于原字段,通常更清楚也更有利于优化器。

应用还应统一存储时区和展示时区。跨时区日报要先确定“某一天”按用户、业务还是 UTC 边界计算。

示例

示例数据表

表名:orders
orders
idcustomer_idproduct_idnamedepartmentamountstatuscreated_atdiscount
1 101 201 Alice Sales 1200 paid 2026-01-03 0
2 102 202 Bob IT 900 pending 2026-01-08 50
3 101 201 Cindy Sales 1500 paid 2026-02-02 100
4 104 203 David HR 700 cancelled 2026-02-15 0

优化前 / 不推荐

SELECT * FROM orders WHERE DATE_FORMAT(created_at, '%Y-%m') = '2026-02' ORDER BY created_at;

优化前运行结果

result
idcustomer_idproduct_idnamedepartmentamountstatuscreated_atdiscount
3 101 201 Cindy Sales 1500 paid 2026-02-02 100
4 104 203 David HR 700 cancelled 2026-02-15 0

优化后 / 推荐

SELECT * FROM orders WHERE created_at >= '2026-02-01' AND created_at < '2026-03-01' ORDER BY created_at;

优化后运行结果

result
idcustomer_idproduct_idnamedepartmentamountstatuscreated_atdiscount
3 101 201 Cindy Sales 1500 paid 2026-02-02 100
4 104 203 David HR 700 cancelled 2026-02-15 0

为什么这样更好:半开区间覆盖二月的全部时间精度,并让条件直接作用于 created_at。

这篇内容是否清楚?