datediff()是mysql计算两日期天数差的直接函数,首参为结束日期、次参为起始日期,仅支持date/datetime类型并自动截断时间部分;遇null返回null,需用coalesce或is null处理;高精度需求应改用timestampdiff();跨时区需先统一时区。

DATEDIFF() 是最直接的函数,但要注意参数顺序
MySQL 提供 DATEDIFF() 函数专门计算两个日期之间的天数差,结果是整数,单位为“天”。它只接受两个 DATE 或 DATETIME 类型参数,且**第一个参数是结束日期,第二个是起始日期**——顺序反了会得到负值,这点容易被忽略。
常见错误现象:写成 DATEDIFF('2023-01-01', '2023-01-10'),结果是 -9,而非预期的 9。
- 正确用法:
DATEDIFF('2023-01-10', '2023-01-01')→ 返回 9 - 支持列名:
DATEDIFF(order_shipped_at, order_created_at),适用于表中存储的日期字段 - 自动截断时间部分:传入
DATETIME值(如'2023-01-01 14:30:00')时,只取日期部分参与计算
遇到 NULL 值时 DATEDIFF() 返回 NULL,需主动处理
如果任一参数为 NULL,DATEDIFF() 直接返回 NULL,不会报错但可能破坏后续聚合或条件判断。生产环境中字段缺失很常见,不能依赖应用层补全。
- 用
COALESCE()提供默认日期:DATEDIFF(COALESCE(end_date, '2099-01-01'), COALESCE(start_date, '1970-01-01')) - 用
IS NULL过滤或标记:CASE WHEN end_date IS NULL OR start_date IS NULL THEN -1 ELSE DATEDIFF(end_date, start_date) END - 注意:用
0或NULL作为占位值会影响平均值、最大值等统计结果,要结合业务含义决定策略
需要包含时间精度?别用 DATEDIFF(),改用 TIMESTAMPDIFF()
如果两个字段是 DATETIME 类型,且你关心的是“精确到小时/分钟的差值”,DATEDIFF() 就不够用了——它永远只算日期差。这时该用 TIMESTAMPDIFF(),它支持指定单位。
- 计算小时差:
TIMESTAMPDIFF(HOUR, '2023-01-01 10:00:00', '2023-01-02 15:30:00')→ 返回 29 - 单位可选:
SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、QUARTER、YEAR - 参数顺序和
DATEDIFF()一致:结束时间在前,开始时间在后 - 性能提示:在大表上对 DATETIME 字段频繁调用
TIMESTAMPDIFF()可能无法走索引,尤其当函数作用于列时(如TIMESTAMPDIFF(DAY, created_at, NOW()) > 30)
跨时区或带时区的时间戳?先统一时区再计算
MySQL 的 DATEDIFF() 和 TIMESTAMPDIFF() 都基于服务器当前时区解释时间值。如果你的字段存的是 UTC 时间(比如 TIMESTAMP 类型),而客户端按本地时区读写,直接计算可能出错。
- 确认字段类型:
TIMESTAMP自动转为系统时区;DATETIME不做转换,原样存储 - 安全做法:显式转换后再算,例如把 UTC 时间转成本地时区:
DATEDIFF(CONVERT_TZ(end_time, '+00:00', @@session.time_zone), CONVERT_TZ(start_time, '+00:00', @@session.time_zone)) - 更稳妥的方式是在应用层统一时区处理,数据库只存标准 UTC,避免在 SQL 层做复杂时区运算
'2023-01-01' 当作日期用,MySQL 虽能解析,但在某些严格模式下会警告,且无法利用日期索引。











