mysql中datediff(end_date, start_date)返回正数天数,参数反序得负值;postgresql用日期相减或extract;sql server的datediff(day)按边界计数而非24小时。

MySQL里用DATEDIFF()算天数,但参数顺序不能反
DATEDIFF()在MySQL中只接受两个日期参数,且必须是DATEDIFF(end_date, start_date),结果为正数表示end_date在start_date之后的天数。如果传反了(比如DATEDIFF('2023-01-01', '2023-01-10')),会返回负值,容易被忽略导致逻辑错误。
- 日期字段或字面量都需是合法DATE/DATETIME类型,字符串如
'2023-01-01'会被自动转换,但'01/01/2023'可能解析失败 - 时分秒部分会被截断,
DATEDIFF('2023-01-01 23:59:59', '2023-01-01 00:00:01')仍返回0 - 不支持跨时区自动归一化,若字段含时区信息(如
TIMESTAMP WITH TIME ZONE),需先转为统一时区再计算
PostgreSQL没有DATEDIFF(),得用减法和EXTRACT()
PostgreSQL不提供DATEDIFF()函数,直接用两个DATE相减即可得到天数间隔,例如'2023-01-10'::DATE - '2023-01-01'::DATE返回9。但注意:两个TIMESTAMP相减返回的是INTERVAL,需进一步提取天数。
- 对
TIMESTAMP类型,用EXTRACT(DAY FROM (end_ts - start_ts))只取日部分,会丢失跨月/年的总天数(如1个月≠30天) - 更稳妥的是用
(end_ts::DATE - start_ts::DATE),强制转为日期再减,避免时间部分干扰 - 若涉及夏令时切换,
TIMESTAMP WITH TIME ZONE相减可能因时钟跳变产生非整数天,建议统一转为UTC再计算
SQL Server的DATEDIFF()单位灵活,但默认按“边界跨越”计数
SQL Server的DATEDIFF(day, start, end)看似直观,但它统计的是“day单位的边界跨越次数”,不是纯粹的24小时差。例如DATEDIFF(day, '2023-01-01 23:00', '2023-01-02 01:00')返回1,哪怕只差2小时。
- 若要严格按24小时周期算天数,应改用
DATEDIFF(second, start, end) / 86400.0再FLOOR或ROUND -
day、dd、d三者等价,但datediff(d, ...)可读性差,易与datepart混淆 - 起始/结束值为
NULL时整个表达式返回NULL,做条件过滤前需用IS NOT NULL显式判断
跨数据库写法兼容性差,别硬套一个函数名
想写一次SQL跑多个数据库?DATEDIFF()的参数顺序、单位参数、NULL处理全都不一致,强行抽象只会埋坑。实际项目中更可靠的做法是:
- 在应用层统一处理日期差(如Python用
(end - start).days,Java用ChronoUnit.DAYS.between()) - 若必须在SQL里算,按目标数据库选原生方式:MySQL用
DATEDIFF(),PostgreSQL用减法,SQL Server用DATEDIFF(day, ...) - 测试时务必覆盖边界情况:同一天、跨年、跨闰年、含时间戳、NULL值
日期计算看着简单,但时区、精度、NULL、函数语义差异这些点,漏掉一个就可能让“相差1天”的业务逻辑出错。











