DATEDIFF函数基本用法是计算两个日期间的天数差,参数顺序为DATEDIFF(end_date, start_date),结果为整数且不自动取绝对值;若顺序颠倒则返回负值,DATETIME类型会自动截断时间部分,NULL或非法日期导致结果为NULL,WHERE中直接对字段使用会失效索引。

DATEDIFF函数的基本用法和参数顺序
DATEDIFF 只接受两个 DATE 或 DATETIME 类型的参数,且顺序固定:第一个是结束日期,第二个是起始日期。结果是整数,单位为“天”,正数表示结束日在起始日之后。
常见错误是把参数顺序搞反,比如写成 DATEDIFF('2023-01-01', '2023-01-10'),结果是 -9,而不是预期的 9。别指望它自动取绝对值——它就是按减法算:end_date - start_date。
- 如果字段是
DATETIME类型(如created_at),DATEDIFF会自动截断时间部分,只比较日期 - 不支持毫秒、小时或月份粒度;要算月差得用
TIMESTAMPDIFF(MONTH, ...) - 第二个参数不能为
NULL,否则整个表达式返回NULL
在WHERE条件中用DATEDIFF过滤最近N天的数据
这是最常见也最容易出错的场景。比如查“过去7天内创建的订单”,别写成 DATEDIFF(NOW(), created_at) <= 7 —— 看似合理,但会导致索引失效(因为对字段 created_at 做了函数计算)。
正确做法是把函数移到右边,让左边保持裸字段:
- ✅
created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY) - ❌
DATEDIFF(NOW(), created_at) <= 7
这样数据库才能走 created_at 上的索引。如果非要用 DATEDIFF,至少确保它不包裹字段,例如 DATEDIFF('2024-05-01', '2024-04-25') 这种纯常量计算没问题。
与TIMESTAMPDIFF的区别:什么时候不该用DATEDIFF
DATEDIFF 只能算“日差”,而且忽略时间部分;遇到需要精确到小时、跨月、或考虑时区的情况,必须换 TIMESTAMPDIFF。
- 要算两个时间点之间相差多少小时?用
TIMESTAMPDIFF(HOUR, start_time, end_time),不是DATEDIFF - 两个日期跨月(如 '2023-01-31' 和 '2023-02-01'),
DATEDIFF返回 1,但业务上可能需要“整月”概念,这时得用TIMESTAMPDIFF(MONTH, ...) -
TIMESTAMPDIFF支持YEAR、QUARTER、WEEK等单位,DATEDIFF不支持
另外注意:TIMESTAMPDIFF 的参数顺序和 DATEDIFF 一致,但它的单位是第一个参数,别漏掉。
NULL值和非法日期导致的结果意外
DATEDIFF 对非法日期(如 '2023-02-30')不会报错,而是静默转成 NULL,最终整个表达式返回 NULL。这在 WHERE 或 ORDER BY 中容易引发逻辑漏洞。
- 检查数据质量:用
SELECT * FROM t WHERE date_col NOT REGEXP '^[0-9]{4}-[0-9]{2}-[0-9]{2}$'找格式异常 - 配合
COALESCE避免 NULL 干扰:比如COALESCE(DATEDIFF(end_dt, start_dt), 0) -
STR_TO_DATE()转换字符串前先确认格式,否则失败也得回NULL
真正麻烦的是那种“看起来合法但实际无效”的日期,比如 '0000-00-00'——MySQL 5.7 默认允许,但 DATEDIFF 对它返回 NULL,而你可能根本没意识到字段里混进了这种值。


















