如何在SQL Server的WHERE子句中避免日期转换以优化查询性能?
无需转换的SQL Server日期过滤最优方案
你的核心问题是对日期字段执行了字符串转换操作,这导致SQL Server无法利用字段上的索引,被迫对全表数据做转换运算,直接拉低了查询性能。最优解决方式是直接基于日期/日期时间类型做比较,完全避免转换字段,具体修改如下:
关键修改点
- 移除
S.Date的字符串转换:原语句中CONVERT(CHAR(23), S.Date, 121) BETWEEN @DateFrom AND @DateTo会让S.Date上的索引失效,改成直接用日期类型比较。 - 移除
EntryDate的字符串转换:原语句中对COALESCE(S.EntryDate, '1900-01-01')的转换同样没必要,直接保留日期类型比较即可。
修改后的完整查询
SELECT S.* FROM Delivery_Records S (NOLOCK) LEFT JOIN TBCustomers C1 (NOLOCK) ON S.CustomerAgreementCode = C1.CustomerID COLLATE Database_Default INNER JOIN TL_Customers C2 (NOLOCK) ON S.PrimaryAgreementCode = C2.CustomerID COLLATE Database_Default LEFT JOIN L_Customers C3 (NOLOCK) ON S.TransferAgreementCode = C3.CustomerID COLLATE Database_Default WHERE (S.GrowthCycle = 'a') AND (S.Date BETWEEN @DateFrom AND @DateTo) AND (COALESCE(S.EntryDate, '1900-01-01') >= @CreateDateFrom) AND (S.WarehouseCode = 't') AND (S.ContractHolder = '') AND (S.Identity= '-0000-0000-000000000000') AND (S.OwnershipType = @OwnName OR @OwnName = 9) ORDER BY S.RecordID
额外注意事项
- 保证变量类型匹配:确保
@DateFrom、@DateTo、@CreateDateFrom的类型和S.Date、S.EntryDate的类型完全一致(比如都是datetime或datetime2),不要用字符串类型的变量传递日期值。 - 处理日期参数的边界:如果
@DateTo是仅包含年月日的date类型参数,需要将其转换为当天的最后时刻,避免漏掉当天非0点的记录,示例代码:-- 将date类型的@DateTo转换为datetime类型的当天最后一刻 SET @DateTo = DATEADD(ms, -3, CAST(DATEADD(day, 1, @DateTo) AS datetime)); - 优化索引:如果
S.Date或S.EntryDate上没有索引,建议创建包含这些字段的复合索引(结合GrowthCycle、WarehouseCode等过滤条件),进一步提升查询效率。
内容的提问来源于stack exchange,提问作者Immortal
相关产品推荐
相关产品推荐

