datediff仅比较日期部分而忽略时分秒,timestampdiff则基于完整时间戳计算并向下取整,支持多种时间单位且单位须大写、顺序为(timestampdiff(unit,start,end)),where中对字段用datediff会导致索引失效。

DATEDIFF只看年月日,TIMESTAMPDIFF才真正算时间差
DATEDIFF('2024-03-10 23:59:59', '2024-03-10 00:00:00') 返回 0 —— 它直接扔掉时分秒,只比对日期部分。而 TIMESTAMPDIFF(DAY, '2024-03-10 00:00:00', '2024-03-10 23:59:59') 也返回 0,但这是因为它按完整时间戳做除法(总秒数 ÷ 86400),不是“截断”,是“向下取整”。关键区别在于:前者天生忽略时间,后者虽返回整数天,但底层参与了完整时间计算,为换 HOUR/MINUTE 留了接口。
TIMESTAMPDIFF的单位参数必须大写,且顺序固定为(TIMESTAMPDIFF(unit, start, end))
写 TIMESTAMPDIFF(day, d1, d2) 会报错;必须用 TIMESTAMPDIFF(DAY, d1, d2)。单位只能是 SECOND、MINUTE、HOUR、DAY 等全大写字符串。顺序上,第二个参数是起点,第三个是终点,结果 = end − start。这和 DATEDIFF(end, start) 逻辑一致,但别记混:有人误以为 TIMESTAMPDIFF 是 (end, start),其实它明确要求 (unit, start, end)。
WHERE 条件里用 DATEDIFF 就等于主动放弃索引
写 WHERE DATEDIFF(NOW(), created_at) > 7 看似直白,但 MySQL 无法利用 created_at 上的索引,因为函数包裹字段会阻止索引下推。正确做法是改写为 WHERE created_at 。如果字段是 <code>DATE 类型(无时间),用 CURDATE() 更稳妥,避免 NOW() 带时间导致当天数据被意外排除。
NULL 和非法日期的处理方式不同
DATEDIFF(NULL, '2024-01-01') 直接返回 NULL,比较时变成 UNKNOWN,整行被过滤;TIMESTAMPDIFF(DAY, NULL, '2024-01-01') 同样返回 NULL。但遇到非法日期如 '2024-02-30':DATEDIFF 可能静默转成 NULL,而 TIMESTAMPDIFF 会直接报错。这意味着在清洗不规范数据时,TIMESTAMPDIFF 更早暴露问题,但也更脆弱。
TIMESTAMPDIFF(HOUR, ...) 的结果可能比你肉眼数的少 8 小时,而你根本没意识到转换发生了。











