最快捷写法是直接用datediff等函数计算天数差,但需注意mysql与sql server参数顺序相反;postgresql推荐created_at
WHERE 子句里用 DATEDIFF 计算天数差(MySQL / SQL Server)
直接用
DATEDIFF函数比较当前时间和字段时间,是最快捷的写法。但要注意函数参数顺序:MySQL 是DATEDIFF(NOW(), create_time)(大减小),SQL Server 是DATEDIFF(day, create_time, GETDATE())(小减大),顺序反了会得到负值,导致条件失效。常见错误现象:查不到数据,但手工验算明明已超时——大概率是参数顺序写反,或误用了
TIMESTAMPDIFF(MySQL)却没指定单位。使用场景:筛选创建超过 7 天未处理的工单
示例(MySQL):SELECT * FROM orders WHERE status = 'pending' AND DATEDIFF(NOW(), created_at) > 7;注意:
NOW()在执行时求值,不是语句开始时;如果查询耗时长,同一语句内多次调用可能有微小偏差(通常可忽略)。PostgreSQL 用 age() 或普通减法(不依赖函数名统一)
PostgreSQL 没有
DATEDIFF,但支持直接用时间相减,返回 interval 类型,再用EXTRACT提取天数:SELECT * FROM tasks WHERE status = 'new' AND EXTRACT(DAY FROM NOW() - created_at) > 5;也可以用
age(),但age(NOW(), created_at)返回的是带年月日的 interval,不如直接减法直观。容易踩的坑:
- 忘记
EXTRACT(DAY FROM ...),直接写NOW() - created_at > INTERVAL '5 days'虽然也对,但可读性差,且在某些 ORM 中解析困难- 用
created_at 更推荐——它能走索引,而 <code>EXTRACT(...)会导致字段被函数包裹,无法使用created_at上的索引Oracle 用日期直接相减(结果是天数浮点数)
Oracle 中两个
DATE类型相减,结果就是以“天”为单位的数值(含小数),所以判断逻辑最简洁:SELECT * FROM alerts WHERE status = 'unhandled' AND SYSDATE - created_date > 3;关键点:
- 不要用
TO_DATE(SYSDATE)或其他转换,SYSDATE本身就是 DATE 类型- 如果
created_date是TIMESTAMP,相减仍有效,但精度到秒,结果是小数(比如 3.00012),和整数比较时建议用>= 3或> 2.999避免边界误差- 索引友好:该写法不改变字段形式,
created_date上的索引可正常生效跨数据库兼容写法:用范围条件代替函数包裹字段
如果项目要兼容多种数据库,或者表数据量大、有性能要求,优先避免在字段上套函数。统一改写为“字段小于某个时间点”:
-- 所有主流数据库都支持 SELECT * FROM jobs WHERE status = 'queued' AND created_at <p>Oracle 写成:</p><pre class="brush:php;toolbar:false;">AND created_at <p>SQL Server:</p><pre class="brush:php;toolbar:false;">AND created_at <p>这种写法的关键优势是:所有数据库都能对 <code>created_at</code> 字段使用索引。而一旦写成 <code>DATEDIFF(NOW(), created_at) > 10</code>,MySQL 和 SQL Server 就没法走索引了。</p><p>复杂点在于不同数据库的“减法语法”不一致,但只要把计算逻辑移到右边常量侧,就绕开了函数位置陷阱。上线前务必确认目标库的日期字面量格式和运算符支持——比如 SQLite 用 <code>datetime('now', '-10 days')</code>,就不能混用 <code>INTERVAL</code>。</p>











