Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this date comparison condition SARG-able in SQL?

Is this condition sargable?

AND  DATEDIFF(month,p.PlayerStatusLastTransitionDate,@now) BETWEEN 1 AND 7)

My rule of thumb is that a function on the left makes condition non sargable.. but in some places I have read that BETWEEN clause is sargable. So does any one know for sure?

For reference:

  • What makes a SQL statement sargable?
  • http://en.wikipedia.org/wiki/Sargable

NOTE: If any guru ends here, please do update Sargable Wikipedia page. I updated it a little bit but I am sure it can be improved more :)

like image 403
Oscar Foley Avatar asked Jun 01 '12 16:06

Oscar Foley


People also ask

What is Sarg in SQL?

Daniel Janik, 2017-08-31. SARG is short for Search Argument. This is an important tuning term and something every developer and DBA should know.

How do I get Currentdate in SQL?

SQL Server GETDATE() Function The GETDATE() function returns the current database system date and time, in a 'YYYY-MM-DD hh:mm:ss. mmm' format. Tip: Also look at the CURRENT_TIMESTAMP function.


2 Answers

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:

enter image description here

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

enter image description here

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:

enter image description here

enter image description here

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.

like image 96
Aaron Bertrand Avatar answered Sep 28 '22 01:09

Aaron Bertrand


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).

like image 21
Abe Miessler Avatar answered Sep 28 '22 02:09

Abe Miessler