应将时间计算移至常量侧以保持索引字段裸露,避免在WHERE中对索引列使用函数;DATEDIFF易因日历边界导致逻辑错误,超时判断应改用TIMESTAMPDIFF或DATEDIFF配合精确单位;跨数据库需适配语法差异,最稳妥方案是应用层生成时间边界。

因为它们能安全地把“动态时间边界”转成确定的日期值,避免在WHERE里对索引字段用函数——这是范围查询性能的关键。
DATEADD必须写在常量侧,否则索引失效
你不能写 WHERE DATEADD(day, 7, create_time) > '2026-08-20',这会让MySQL/SQL Server放弃使用 create_time 上的索引。真正有效的写法是把计算移到右边:
-
WHERE create_time > DATEADD(day, -7, '2026-08-20')(SQL Server) -
WHERE create_time > DATE_SUB('2026-08-20', INTERVAL 7 DAY)(MySQL) - 本质是:让索引字段保持裸露,只对固定值做运算
DATEDIFF不适合做“超时判断”,容易逻辑错
它算的是日历边界跨越数,不是真实时间差。比如 DATEDIFF(hour, '2026-08-27 23:59:59', '2026-08-28 00:00:01') 返回 1 小时,但实际只差 2 秒。
- 要判断“是否超过24小时”,该用
TIMESTAMPDIFF(HOUR, start_time, NOW()) > 24(MySQL)或DATEDIFF(MINUTE, start_time, GETDATE()) > 1440(SQL Server) -
DATEDIFF的单位参数不校验拼写,'days'或'DAY'都可能静默返回 NULL - 跨时区连接下,
DATEDIFF对TIMESTAMP和DATETIME字段行为不同,结果会漂移
跨数据库写范围查询,别硬套同一套函数
PostgreSQL 支持 event_time >= NOW() - INTERVAL '7 days' 这种直观写法;SQL Server 必须用 DATEADD(day, -7, GETDATE());MySQL 则要 DATE_SUB(NOW(), INTERVAL 7 DAY)。三者语法、单位大小写、引号规则全都不兼容。
- 单位大小写敏感:MySQL 要
DAY(大写),SQL Server 要day(小写),PostgreSQL 接受'7 days'(带s、单引号) - INTERVAL 关键字不可省:MySQL/PostgreSQL 必须写,SQL Server 完全不用
- 最稳妥的跨库做法是:应用层生成边界时间字符串,SQL里直接用
BETWEEN ? AND ?
真正难的不是写出能跑的语句,而是意识到 DATEADD/DATEDIFF 的“边界计算”本质 —— 它们不是数学加减,而是日历翻页。一旦当成精确时间差用,凌晨三点的数据就悄悄漏掉了。

















