WHERE date_col >= CAST(GETDATE() AS DATE) 且 date_col = '2026-07-21',同时 order_date = @start、col = DATE(NOW())、order_time 条件并存。

直接用 WHERE date_col >= CAST(GETDATE() AS DATE) 和 date_col 最稳妥,别用 <code>CAST(date_col AS DATE) = CAST(GETDATE() AS DATE) —— 它会让索引失效。
为什么不能直接用 = 比较日期部分?
很多人写 CAST(order_date AS DATE) = CAST(GETDATE() AS DATE) 看似简洁,但 SQL Server 会对每一行的 order_date 字段做转换,导致无法走索引。哪怕该字段上有 datetime 或 datetime2 类型的索引,也会退化为全表扫描。
真正高效的方式是把条件写成「范围查询」:从今天 00:00:00.000 开始,到明天 00:00:00.000 结束(不包含)。
-
GETDATE()返回带时分秒毫秒的当前时间,比如2026-07-21 10:12:33.456 -
CAST(GETDATE() AS DATE)截断为2026-07-21,但单独用它做等值比较仍会触发函数计算 - 所以应写成:
WHERE order_date >= '2026-07-21' AND order_date —— 这个形式能命中索引
DATEDIFF(dd, col, GETDATE()) = 0 为什么也慢?
这个写法在语义上没错,但和 CAST 一样,是对 col 列逐行调用函数,同样破坏索引使用。执行计划里常看到 Compute Scalar + Index Scan,而不是预期的 Index Seek。
尤其当表有几百万行、且 order_date 是高频查询字段时,性能差距可能达数秒甚至分钟级。
- 它适合临时查小表、或开发调试阶段快速验证逻辑
- 生产环境的 WHERE 条件里,优先避免对列名本身做任何函数包装
- 如果必须用
DATEDIFF,至少确保它出现在右侧,比如WHERE DATEDIFF(DAY, '2026-07-21', order_date) = 0—— 但这仍不如范围写法直观可靠
不同数据类型要小心隐式转换
如果你的日期字段是 date 类型(无时间部分),那 = CAST(GETDATE() AS DATE) 是安全的,因为两边都是纯日期,SQL Server 不需要对列做运行时转换。
但一旦字段是 datetime、datetime2 或 smalldatetime,就必须按范围写法处理,否则等于放弃索引。
-
date类型字段:可接受=写法,但范围写法依然更统一、更易复用 -
datetime2(7)字段:哪怕只存了2026-07-21 00:00:00.0000000,用=比较也大概率失败(毫秒精度差异) - 最保险的做法:统一用
WHERE col >= @start AND col ,其中 <code>@start = CAST(GETDATE() AS DATE),@end = DATEADD(DAY, 1, @start)
跨数据库写法差异要留意
SQL Server 的 GETDATE() 在 MySQL 是 NOW(),在 PostgreSQL 是 CURRENT_DATE 或 NOW()::DATE,Oracle 是 TRUNC(SYSDATE)。但核心原则不变:避免对列函数运算,坚持范围查询。
例如在 MySQL 中,正确写法是:
SELECT * FROM orders WHERE order_time >= DATE(NOW()) AND order_time < DATE_ADD(DATE(NOW()), INTERVAL 1 DAY);
注意这里用了 DATE(NOW()) 而不是 DATE(order_time) —— 后者同样会导致索引失效。
真正容易被忽略的点是:哪怕你记得用范围,也可能漏掉「严格左闭右开」这个边界。写成 明天 00:00:00 就会多捞出一条边界记录,而 <code> 才能精确卡死在今日末尾。

















