Is this date comparison condition SARG-able in SQL?

独自空忆成欢 提交于 2019-11-28 12:13:53
Aaron Bertrand

Using AdventureWorks, if we look at these two equivalent queries:

SELECT OrderDate FROM Sales.SalesOrderHeader
WHERE DATEDIFF(month,OrderDate,GETDATE()) BETWEEN 1 AND 7;

SELECT OrderDate FROM Sales.SalesOrderHeader
WHERE OrderDate >= DATEADD(MONTH, -7, GETDATE())
  AND OrderDate <= DATEADD(MONTH, -1, GETDATE());

In both cases we see a clustered index scan:

But notice the recommended/missing index only on the latter query, since it's the only one that could benefit from it:

If we add an index to the OrderDate column, then run the queries again:

CREATE INDEX dt ON Sales.SalesOrderHeader(OrderDate);
GO

SELECT OrderDate FROM Sales.SalesOrderHeader
WHERE DATEDIFF(month,OrderDate,GETDATE()) BETWEEN 1 AND 7;

SELECT OrderDate FROM Sales.SalesOrderHeader
WHERE OrderDate >= DATEADD(MONTH, -7, GETDATE())
  AND OrderDate <= DATEADD(MONTH, -1, GETDATE());

We see much difference - the latter uses a seek:

Notice too how the estimates are way off for your version of the query. This can be absolutely disastrous on a large data set.

There are very few cases where a function or other expression applied to the column will be sargable. One case I know of is CONVERT(DATE, datetime_column) - but that particular optimization is undocumented, and I recommend staying away from it anyway. Not only because you'd be implicitly suggesting that using functions/expressions against columns is okay (it's not in every other scenario), but also because it can lead to wasted reads and disastrous estimates.

Abe Miessler

I would be very surprised if that was sargable. One option might be to rewrite it as:

WHERE p.PlayerStatusLastTransitionDate >= DATEADD(month,1,CAST(@now AS DATE))
AND   p.PlayerStatusLastTransitionDate <= DATEADD(month,7,CAST(@now AS DATE))

Which I believe will be sargable (even though it's not quite as pretty).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!