mysql中datediff(end_date, start_date)返回两日期整数天数差,顺序决定正负;自动截断datetime时间部分,不支持小时等精度,null值导致结果为null。

MySQL 用 DATEDIFF() 计算天数差,但注意参数顺序
DATEDIFF() 只接受两个 DATE 或 DATETIME 类型参数,返回第一个减第二个的天数(end_date - start_date)。传反了会得到负数,不是绝对值:
SELECT DATEDIFF('2024-05-10', '2024-05-01'); -- 返回 9<br>SELECT DATEDIFF('2024-05-01', '2024-05-10'); -- 返回 -9
- 如果字段是
DATETIME类型,DATEDIFF()自动截断时间部分,只比日期 - 不能直接算小时或分钟,要换用
TIMESTAMPDIFF() - 若日期字段可能为
NULL,记得加WHERE date1 IS NOT NULL AND date2 IS NOT NULL,否则整行结果为NULL
PostgreSQL 用减法运算符,但类型必须匹配
PostgreSQL 允许直接用 - 计算两个 DATE 值,结果是 INTEGER 天数;但两个 TIMESTAMP 相减返回的是 INTERVAL,不能直接当数字用:
SELECT '2024-05-10'::DATE - '2024-05-01'::DATE; -- 返回 9<br>SELECT '2024-05-10 14:30'::TIMESTAMP - '2024-05-01 09:00'::TIMESTAMP; -- 返回 "9 days 05:30:00"
- 想从
INTERVAL提取天数,得用EXTRACT(DAY FROM ...),但注意它只取日部分,不累计小时折算 - 更稳妥的跨类型做法是先用
CAST(... AS DATE)统一转成日期再减 - 时区敏感:如果字段带时区(
TIMESTAMPTZ),相减结果已按 UTC 对齐,无需手动转换
SQL Server 的 DATEDIFF() 单位易错,且默认四舍五入
DATEDIFF() 在 SQL Server 中必须指定单位(如 day、month),但它计算的是“边界跨越数”,不是精确跨度:
SELECT DATEDIFF(day, '2024-01-01 23:59', '2024-01-02 00:01'); -- 返回 1<br>SELECT DATEDIFF(month, '2024-01-31', '2024-02-01'); -- 返回 1(哪怕只差1天)
- 单位参数是
dd、mm、yy等缩写,不能写成days或day(会报错) - 想算精确小时差,用
DATEDIFF(hour, ...),但要注意跨夏令时可能偏差 1 小时 - 如果需要小数天数(比如 1.5 天),得自己用
DATEDIFF(second, ...)/86400.0
跨数据库可移植方案:用 Julian Day 转换(慎用)
标准 SQL 没有统一日期差函数,真要兼容多库,最可靠的是把日期转成数值再减——但各库 Julian Day 实现不同:
- SQLite 有
julianday(),返回浮点数,相减即得天数(含小数) - Oracle 用
date_col - other_date_col本身就返回天数(支持小数),但只限 Oracle - 不要硬套一个公式去“手算儒略日”,误差大且维护成本高
- 实际项目中,优先按目标数据库选原生函数,而不是追求语法一致
日期差看着简单,但单位语义、空值处理、时区、类型隐式转换这四点,任何一个没对齐都会让结果偏一天甚至更多。











