<p>最稳查昨天数据的方式是 CURDATE() - INTERVAL 1 DAY;它返回纯日期,配合 DATE() 可精准匹配 DATETIME 字段的日期部分,但索引失效,更优写法是 create_time >= (CURDATE() - INTERVAL 1 DAY) AND create_time < CURDATE()。</p>

查昨天的数据:用 CURDATE() 减 INTERVAL 1 DAY 最稳
MySQL 中查“昨天”不能直接写 'yesterday',得靠日期运算。最可靠的方式是 CURDATE() - INTERVAL 1 DAY,它返回不带时间的纯日期(如 2024-06-15),和 DATE() 配合能精准匹配 DATETIME 字段的日期部分。
常见错误是用 NOW() - INTERVAL 1 DAY,它返回带时分秒的时间戳(如 2024-06-15 14:23:01),若字段是 DATETIME 且你只想要“整日数据”,直接比较会漏掉今天 00:00–14:22 的记录。
- 推荐写法:
WHERE DATE(create_time) = CURDATE() - INTERVAL 1 DAY - 如果
create_time有索引,DATE(create_time)会导致索引失效;更优写法是:WHERE create_time >= (CURDATE() - INTERVAL 1 DAY) AND create_time -
CURDATE()返回的是服务器本地时区日期,确认你的 MySQL 时区设置(SELECT @@time_zone;)与业务一致
查今天的数据:别只用 CURDATE(),要配合范围查询
CURDATE() 本身只返回日期,不能直接用于 DATETIME 字段的等值比较——因为 create_time = CURDATE() 实际被隐式转成 create_time = '2024-06-16 00:00:00',只命中这一秒。
- 安全写法(索引友好):
WHERE create_time >= CURDATE() AND create_time - 如果字段是
DATE类型(无时间),可用WHERE create_date = CURDATE(),此时索引可正常生效 - 注意:
NOW()和CURDATE()在同一个查询中多次调用,结果一致;但跨语句执行时可能因执行间隔产生微小偏差(不过对“今天”判定无实质影响)
INTERVAL 的单位和方向容易写反
INTERVAL 后面跟数字和单位,顺序固定,不能颠倒,也不能省略空格。写错会报错或逻辑出错。
- 正确:
CURDATE() + INTERVAL 7 DAY(7天后)、CURDATE() - INTERVAL 1 MONTH(上月同日) - 错误写法举例:
CURDATE() + INTERVAL DAY 7(语法错误)、CURDATE() + INTERVAL -1 DAY(虽能运行但可读性差,不推荐) - 单位支持
DAY、WEEK、MONTH、YEAR、HOUR、MINUTE等,但INTERVAL 1.5 DAY不合法,需换算为INTERVAL 36 HOUR - 跨月计算要注意日溢出,比如
'2024-03-31' - INTERVAL 1 MONTH结果是'2024-02-29'(不是 3月31日→2月31日报错,MySQL 自动归整)
时区和字段类型不匹配导致查不到数据
很多线上问题不是逻辑写错,而是时区或类型没对齐。比如应用写入用的是 UTC 时间,但数据库时区设为 +08:00,这时 CURDATE() 拿到的是东八区日期,而数据实际存储的是 UTC 的 2024-06-15 16:00:00(对应北京时间 6月16日 00:00:00),直接按本地 CURDATE() 查就会少一天。
- 先确认数据写入时区:
SELECT create_time, UNIX_TIMESTAMP(create_time) FROM logs LIMIT 1;对比本地时间和时间戳 - 统一方案:要么所有写入转成本地时区再存,要么查询时用
CONVERT_TZ()转换,例如:WHERE DATE(CONVERT_TZ(create_time, '+00:00', '+08:00')) = CURDATE() -
TIMESTAMP类型字段会自动按当前时区转换,DATETIME则原样存储,这点必须清楚——混用时尤其容易踩坑
日期计算看着简单,真正上线后出问题,八成卡在时区、字段类型、索引失效这三处。写完记得用 EXPLAIN 看执行计划,确认是否走了索引。

















