DATEDIFF() 返回两日期间整数天数差,忽略时间部分;参数顺序决定正负,不支持NULL、毫秒和时区;需高精度用TIMESTAMPDIFF();WHERE中函数作用于列会导致索引失效。
DATEDIFF() 是 MySQL 里最常用也最直观的日期差计算函数,它返回两个日期之间相差的完整天数(只算日期部分,忽略时间)。结果是整数,正负取决于参数顺序:DATEDIFF(end_date, start_date) 返回正数表示 end 在 start 之后。
start_date 是 '2024-01-01',end_date 是 '2024-01-05',DATEDIFF('2024-01-05', '2024-01-01') 返回 4
'2024-01-01 14:30:00' 会被截断为 '2024-01-01')NULL,否则整个结果为 NULL,建议提前用 IFNULL() 或 COALESCE() 处理TIMESTAMP 类型,DATEDIFF() 也只比对日期部分当你要算“从 2024-01-01 10:00:00 到 2024-01-02 15:30:00 相差多少小时”,DATEDIFF() 就不够用了。这时候得用 TIMESTAMPDIFF(),它支持按指定单位(DAY、HOUR、MINUTE 等)计算两个 datetime 的精确差值。
TIMESTAMPDIFF(unit, datetime_expr1, datetime_expr2),注意:第二个参数是起点,第三个是终点,和 DATEDIFF() 顺序一致TIMESTAMPDIFF(HOUR, '2024-01-01 10:00:00', '2024-01-02 15:30:00'),结果是 27
SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、QUARTER、YEAR)DATE,一个是 DATETIME),MySQL 会隐式转换,但可能出人意料——DATE 被转成当天零点,容易导致多算或少算一整天在查询中写 WHERE DATEDIFF(NOW(), created_at) > 30 看似合理,但会让 created_at 字段上的索引完全失效,因为函数作用于列上,优化器无法使用 B+ 树索引做范围扫描。
WHERE created_at
WHERE created_at
TIMESTAMPDIFF(DAY, created_at, NOW()) > 30 也会使索引失效,必须改写为 created_at
DATEDIFF() 只认日历天数,而 TIMESTAMPDIFF(MONTH, ...) 计算的是“月份差”,不是简单除以 30。比如从 1 月 31 日到 2 月 28 日(非闰年),DATEDIFF() 返回 28,但 TIMESTAMPDIFF(MONTH, '2024-01-31', '2024-02-28') 返回 0,因为还没满一个月。
TIMESTAMPDIFF(MONTH, d1, d2) 的逻辑是:先比较年份差 ×12,再加月份差,最后看日部分是否“够格”——只有当 d2 的日 ≥ d1 的日时,才计入这个月TIMESTAMPDIFF(MONTH, '2024-01-15', '2024-02-14') 是 0,而 '2024-01-15' 到 '2024-02-15' 才是 1
DATEDIFF() 除以 30 来模拟月差,误差会很大;也别用 TIMESTAMPDIFF(MONTH, ...) 去反推具体天数——它不保证可逆实际业务里最容易被忽略的是时间类型隐式转换和索引失效这两点。尤其当表数据量上去之后,一个没注意的 DATEDIFF() 写法可能让查询从毫秒变几秒。