应优先使用范围查询而非DATEDIFF等函数做WHERE条件,如CreatedTime >= DATEADD(day, DATEDIFF(day, 0, GETDATE()) - 7, 0);注意GETDATE()与SYSDATETIME()精度差异及索引失效风险。

DATEDIFF(day, 列名, GETDATE()) 返回的是天数差,但别直接用它做WHERE条件
很多人写 DATEDIFF(day, CreatedTime, GETDATE()) 想查近7天数据,结果发现今天凌晨0点之后的记录漏掉了——因为 <code>DATEDIFF(day, ...) 只比较年月日部分,会把时间精度“截断”。比如 DATEDIFF(day, '2024-05-01 23:59:59', GETDATE()) 在5月2日00:00:01时就返回1,看似符合
真正安全的做法是把“近N天”转换成一个确定的起始时间点,再用范围查询:
- 用
DATEADD(day, -7, GETDATE())得到7×24小时前的精确时间戳 - WHERE条件写成
CreatedTime >= DATEADD(day, -7, GETDATE()) - 这样能走索引(如果
CreatedTime有索引),且结果严格按小时粒度对齐
用 DATEDIFF(day, ..., ...) 做分组或排序可以,但别依赖它过滤“最近”
如果你要统计每天新增记录数,GROUP BY DATEDIFF(day, CreatedTime, GETDATE()) 是常见写法,它能把“今天”归为0、“昨天”归为1……逻辑清晰。但注意:DATEDIFF(day, CreatedTime, GETDATE()) = 0 等价于 CAST(CreatedTime AS DATE) = CAST(GETDATE() AS DATE),只匹配当天00:00:00–23:59:59的数据,不包含跨日的毫秒误差问题。
不过仍建议避免在WHERE里用 = 0 或 做主筛选条件,原因同上:语义模糊、难索引、易出偏差。
更推荐用 DATEADD + 范围查询,兼容性好且性能稳定
SQL Server 2008+ 都支持 DATEADD,而且这种写法明确表达了业务意图:“从现在往前推N天”,数据库优化器也更容易生成高效执行计划。
示例(查近7天含今天):
SELECT * FROM Orders WHERE CreatedTime >= DATEADD(day, -7, GETDATE());
如果需要“严格7×24小时”,这个写法没问题;如果业务要求“自然日”(比如今天是5月10日,就要查5月4日00:00起),则改用:
-
CreatedTime >= DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), DAY(GETDATE()) - 7)(SQL Server 2012+) - 或更稳妥的
CreatedTime >= DATEADD(day, DATEDIFF(day, 0, GETDATE()) - 7, 0)(兼容老版本,0表示1900-01-01,DATEADD(day, ..., 0)可清空时间部分)
注意 GETDATE() 和 SYSDATETIME() 的精度差异
GETDATE() 返回 datetime 类型(精度1/300秒),而 SYSDATETIME() 是 datetime2(7)(精度100纳秒)。大多数场景用 GETDATE() 足够,但如果表里 CreatedTime 是 datetime2 类型,且你依赖毫秒级一致性,建议统一用 SYSDATETIME(),否则隐式转换可能影响索引选择或结果边界。
另外,所有这些函数在查询执行瞬间求值一次,不会在每行重复计算,这点不用担心性能。
真正容易被忽略的是:日期函数组合一旦嵌套过深(比如 DATEDIFF(day, DATEADD(...), ...)),不仅可读性下降,SQL Server有时会放弃使用索引——宁可用简单范围,别炫技。

















