最稳查昨天数据的方式是 curdate() - interval 1 day;它返回纯日期,配合 date() 可精准匹配 datetime 字段的日期部分,但索引失效,更优写法是 create_time >= (curdate() - interval 1 day) and create_time
查昨天的数据:用
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_timeCURDATE()返回的是服务器本地时区日期,确认你的 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看执行计划,确认是否走了索引。











