当前位置: 首页
数据库
如何在MySQL中计算两个日期相差天数的详细方法

如何在MySQL中计算两个日期相差天数的详细方法

热心网友 时间:2026-07-17
转载

MySQL中计算日期差常用DATEDIFF(),返回忽略时间的整数天数差,参数顺序决定正负。需时间精度时改用TIMESTAMPDIFF(),支持指定单位。WHERE条件中函数套列名会导致索引失效,应将函数移至等号右侧,保持左侧为裸列名。

在 MySQL 中计算日期差是开发中的常见操作,但也是容易踩坑的高频场景。这里总结了几处关键注意事项:DATEDIFF() 返回的是忽略时间的整数天数差,参数顺序直接决定结果的正负;如果需要考虑时间精度,必须改用 TIMESTAMPDIFF();另外,在 WHERE 条件中直接对列名套用函数,会导致索引失效——这一点最容易被忽视,也最容易引发性能问题。

如何在MySQL中计算两个日期相差的天数?

用 DATEDIFF() 函数直接获取整数天数差

DATEDIFF() 是 MySQL 中最直观的日期差计算函数,没有之一。它返回两个日期之间相差的完整天数,仅识别日期部分,时间部分直接被忽略。结果是一个整数,正负取决于你参数的摆放顺序:DATEDIFF(end_date, start_date)——end 在后,start 在前,如果 end 晚于 start,则返回正数。

举例说明:DATEDIFF('2024-01-05', '2024-01-01') 返回的是 4,不是 5。传入参数时,MySQL 会自动识别 '2024-01-01 14:30:00' 这样的格式,但只取日期部分,时间直接被丢弃。所以,想连同时间一起计算?别指望它。

有几个坑需要提前注意:

  • 不能传入 NULL,否则整个结果直接变为 NULL。建议在排序前先用 IFNULL()COALESCE() 做兜底处理。
  • 不支持毫秒级精度,时区也不纳入考虑。哪怕字段是 TIMESTAMP 类型,它也只关注日期那几位数字。

需要包含时间精度时改用 TIMESTAMPDIFF()

场景变了:想计算“从 2024-01-01 10:00:00 到 2024-01-02 15:30:00 差了多少小时”,DATEDIFF() 就完全无能为力了。这时候必须请出 TIMESTAMPDIFF()——它支持按指定单位进行精确计算,单位可以是 DAYHOURMINUTE,甚至 MONTHYEAR

语法是 TIMESTAMPDIFF(unit, datetime_expr1, datetime_expr2),注意顺序:第二个参数作为起点,第三个参数作为终点,与 DATEDIFF() 保持一致。例如 TIMESTAMPDIFF(HOUR, '2024-01-01 10:00:00', '2024-01-02 15:30:00') 返回 27,非常精确。

单位必须大写,支持的枚举值有:SECONDMINUTEHOURDAYWEEKMONTHQUARTERYEAR
有一个隐蔽的坑:如果两个 datetime 值类型不一致——比如一个是 DATE,一个是 DATETIME——MySQL 会进行隐式转换,DATE 被当作当天零点,这样容易莫名其妙地多算或少算一整天。

WHERE 条件里计算日期差要小心索引失效

很多新手喜欢在查询中写 WHERE DATEDIFF(NOW(), created_at) > 30,看起来挺直观。但这样写,created_at 字段上的索引就直接失效了——函数套在列上,优化器无法进行范围扫描。

正确的做法是把函数移到等号右边:WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY)。如果想更简洁,可以写成 WHERE created_at < NOW() - INTERVAL 30 DAY。核心原则就一条:表达式左边必须是裸列名,不带任何函数或运算。
同理,TIMESTAMPDIFF(DAY, created_at, NOW()) > 30 也会导致索引失效,必须改写成 created_at < NOW() - INTERVAL 30 DAY

跨月/跨年时 DATEDIFF() 和 TIMESTAMPDIFF(MONTH) 行为不同

这两个函数在跨月场景下完全是两套逻辑。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() 写法,可能让原本毫秒级的查询直接飙到数秒,教训确实不少。

来源:https://www.php.cn/faq/2820214.html

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
SQL数据库视图简化开发人员编码的实用方法

SQL数据库视图简化开发人员编码的实用方法

视图适合封装固定逻辑(如固定时间窗口、静态状态过滤)和固定JOIN关系,不宜用于需动态传入参数(如用户ID、日期范围)的查询。视图性能取决于底层索引,而非视图本身。ALTERVIEW仅更新元数据,会短暂阻塞新查询启动,应避开高峰期操作。

时间:2026-07-18 22:24
MySQL decimal使用常见问题及解决方法

MySQL decimal使用常见问题及解决方法

MySQL中的DECIMAL类型用于精确数值计算,通过DECIMAL(M,D)定义精度与标度。常见问题包括精度设置不当导致溢出、计算时精度溢出、插入格式错误等。优化建议:合理设置M和D,可用BIGINT存储分单位,关键列建索引,保持版本更新。

时间:2026-07-18 22:22
MySQL大字段TEXT建立索引导致的性能下降解决方案

MySQL大字段TEXT建立索引导致的性能下降解决方案

TEXT字段无法直接建立常规B+树索引,前缀索引不支持左模糊查询,全文索引受词长、中文分词和更新延迟限制。高效替代方案是使用MD5摘要索引和垂直拆分,将TEXT字段分离到独立表,主表采用DYNAMIC行格式,避免溢出页IO问题。

时间:2026-07-18 22:22
金仓数据库迁移避坑指南:从未被质疑的左连接隐患

金仓数据库迁移避坑指南:从未被质疑的左连接隐患

迁移至金仓KES时,LEFTJOIN若在WHERE中过滤右表非空列,将会触发外连接消除,导致数据结果减少。正确做法是将过滤条件置于ON子句中。金仓KES与主流数据库行为一致,务必通过EXPLAIN仔细检查执行计划,以确保连接语义正确。

时间:2026-07-18 22:22
PostgreSQL与MySQL数据库日志机制深度对比

PostgreSQL与MySQL数据库日志机制深度对比

PostgreSQL仅使用一套WAL日志,就同时实现了MySQL的redo、binlog和undo的全部功能,而MySQL因插件式架构需要三套日志并依赖两阶段提交保证一致性。其多版本并发控制通过追加写实现,无需单独的undo日志,但需要定期执行VACUUM操作清理死元组,防止表膨胀。

时间:2026-07-18 22:22
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 热门数据榜