DATEDIFF()返回首参数减次参数的整数天数,自动截断时间部分;TIMESTAMPDIFF()支持秒、小时等任意单位且语义明确;日期比较应将计算移至WHERE右侧以利用索引。

用 DATEDIFF() 计算天数差,注意参数顺序和返回值符号
DATEDIFF() 只接受两个 DATE 或 DATETIME 类型参数,返回的是「第一个减第二个」的整数天数。比如 DATEDIFF('2024-03-15', '2024-03-10') 返回 5,而反过来写就变成 -5。它会自动截断时间部分——DATEDIFF('2024-03-15 23:59:59', '2024-03-15 00:00:01') 仍返回 0。
- 如果字段是
DATETIME但你只关心日期粒度,DATEDIFF()最简洁 - 别指望它返回小数或带时间的部分——它天生只认“日”
- MySQL 5.7+ 支持
NULL参数,结果也为NULL,不用额外判空
用 TIMESTAMPDIFF() 算秒、小时、月等任意单位
要算秒数,必须用 TIMESTAMPDIFF(),它支持指定单位,且参数顺序和 DATEDIFF() 一致:先结束时间,后开始时间。例如 TIMESTAMPDIFF(SECOND, '2024-03-15 10:00:00', '2024-03-15 10:00:30') 返回 30。
- 单位关键字必须大写:
SECOND、MINUTE、HOUR、DAY、MONTH、YEAR -
TIMESTAMPDIFF(DAY, ...)和DATEDIFF(...)结果相同,但前者更统一、可读性略高 - 跨月计算有陷阱:
TIMESTAMPDIFF(MONTH, '2024-01-31', '2024-02-28')返回1(不是按天数折算),它按日历月份数差算
直接相减得到秒数?小心隐式转换出错
有人试过 UNIX_TIMESTAMP(end_time) - UNIX_TIMESTAMP(start_time),这确实能得秒数,但要注意:UNIX_TIMESTAMP() 对无效日期(如 '0000-00-00')返回 0,而 NULL 会传播为 NULL。如果字段允许零日期且未严格校验,结果可能意外为 0 而非报错。
- 推荐优先用
TIMESTAMPDIFF(SECOND, ...)——语义明确、类型安全、不依赖时间戳范围 -
UNIX_TIMESTAMP()在 MySQL 8.0.28+ 支持TIMESTAMP带时区,但老版本默认按系统时区转,跨服务器易不一致 - 若 start/end 是字符串,确保格式符合
'YYYY-MM-DD HH:MM:SS',否则转换失败返回NULL
WHERE 条件里比较日期差,别在函数里套字段
想查“创建超过7天的记录”,别写 WHERE DATEDIFF(NOW(), created_at) > 7——这会让 created_at 上的索引失效。正确做法是把计算移到右边:
WHERE created_at < DATE_SUB(NOW(), INTERVAL 7 DAY)
同理,查“最近1小时操作”应写 WHERE updated_at > DATE_SUB(NOW(), INTERVAL 1 HOUR),而不是用 TIMESTAMPDIFF() 包裹字段。
- 所有对字段加函数的操作都会阻碍索引使用
-
INTERVAL表达式可被优化器识别并利用索引 - 如果字段是
DATE类型,用DATE_SUB(NOW(), INTERVAL 7 DAY)比NOW() - INTERVAL 7 DAY更清晰,两者等价但前者意图更直白
实际业务里,天数差用 DATEDIFF() 最省心,秒级精度必须上 TIMESTAMPDIFF(SECOND, ...);至于性能,永远让常量计算留在右侧,别碰字段本身。


















