Sargable版本的DateDiff()SQL查询

时间:2017-10-18 16:37:38

标签: sql-server tsql sql-server-2012

我继承了一些C#应用程序代码,它具有流畅的SQL查询构建器,可在我们的代码库中使用。一些更常见的查询应用过滤器,如“今天或之后的日期”。这些过滤器作为查询构建器的元数据存储在SQL表中,在调查性能和死锁问题的同时,我意识到这些查询组件不可思议。

此构建器构建的典型查询如下所示:

DECLARE @systemDate DATETIME
SET @systemDate = [dbo].GetSystemDate()

SELECT [table1].* FROM [dbo].[XXX] AS [table1]
WHERE ... AND DateDiff(d, @systemDate, [table1].PaymentDate) <= 0 
AND ...

PaymentDate列存储为具有时间组件的日期时间。 GetSystemDate()在午夜返回日期时间 - 即2017-10-18 00:00:00.000

问题在于,即使我在覆盖索引中有PaymentDate,SQL Server也无法对其进行搜索,因为它位于DateDiff()函数中。但是,查询构建器的设计使我很容易用一个更高效,可搜索的表达式替换,该表达式将应用于所有构造的SQL查询。

对于以下内容,如果时间组件也在查询列中发挥作用,并且生成的查询需要将相同的结果返回到现有的DateDiff()调用,那么对于以下内容的等效sargable查询是什么?我已经看到其他解决方案使用DateAdd()和比较,但我担心这些行为不同,因为我们的数据中有时间组件。

OperatorDisplayName   OperatorExpression   ValueExpression   ColumnExpression
Today                        =                  0           DateDiff(d, @systemDate, {0})
This Week                    =                  0           DateDiff(ww, @systemDate, {0})
Last Week                    =                 -1           DateDiff(ww, @systemDate, {0})
This Month                   =                  0           DateDiff(m, @systemDate, {0})
Last Month                   =                 -1           DateDiff(m, @systemDate, {0})
On or Before Today          <=                  0           DateDiff(d, @systemDate, {0})
On or After Today           >=                  0           DateDiff(d, @systemDate, {0})
Before Today                 <                  0           DateDiff(d, @systemDate, {0})
After Today                  >                  0           DateDiff(d, @systemDate, {0})

1 个答案:

答案 0 :(得分:0)

由于@systemDate没有时间组件,您可以构建&gt; =&lt;比较:

OperatorDisplayName   OperatorExpression   ValueExpression   ColumnExpression
Today                        =                  0           {0} >= @systemDate AND {0} < DATEADD(d, 1, @systemDate)

您并没有真正以这种方式使用Operator或Value,因为它内置于列表达式中。

星期和月份运算符会变得更复杂,因为您的表达式需要包含代码来计算基于@systemDate的星期/月的第一天,但​​网上已有样本。< / p>