select Name, ProductID
from Production.Product
where Name like 'R%' ;
Looking in the Execution Plan, we see an Index Seek to find the 52 rows, and the seek has a Seek Predicate like this (by looking in either the ToolTip of the operator, the Properties window, or the XML itself):
Seek Keys[1]: Start: [AdventureWorks].[Production].[Product].Name >= Scalar Operator(N'R'), End: [AdventureWorks].[Production].[Product].Name < Scalar Operator(N'S')
This shows that the system looks as the LIKE call, and translates it into a greater-than and less-than query. (Interestingly, have a look at the End Seek Key if you tell it to find entries that start with Z)
select Name, ProductID
from Production.Product
where LEFT(Name,1) = 'R' ;
Unfortunately the LEFT function kills the SARGability. The Execution Plan for this query shows an Index Scan (starting on page one and going to the end), with the Predicate (not, not Seek Predicate, just Predicate) “substring([AdventureWorks select ProductID
from Production.Product
where ProductID + 1 = 901;
This is doing a scan, checking every row, even though we can easily understand what we mean. The same would apply for this query (assuming there’s an index on OrderDate):
select OrderDate
from Sales.SalesOrderHeader
where dateadd(day,1,OrderDate) = '20040101'
;
And perhaps most significantly:
select OrderDate
from Sales.SalesOrderHeader
where dateadd(day,datediff(day,0,OrderDate),0) = '20040101'
;
…which is largely recognised as being an effective method for date truncation (and why you should always compare dates using >= and < instead)
select OrderDate
from Sales.SalesOrderHeader
where cast(OrderDate as date) = '20040101' --NB date is a 2008 datatype
;
This query does a little work to figure out a couple constants (presumably one of them being the date 20040101, and another being 20040102), and then does an Index Seek to get the data.
select OrderDate
from Sales.SalesOrderHeader
where convert(char(8), OrderDate, 112) = '20040101'
;
…but did you really think it would? There’s no relationship between strings and dates.
select OrderDate
from Sales.SalesOrderHeader
where convert(char(6), OrderDate, 112) + '01' = '20040101'
;
But it doesn’t.
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (3)
Commented:
Tim Chapman
Commented:
I finally got off my tail to put my official "Yes" vote above, but you won me over on the first reading.
Cheers,
Kevin
Commented:
btw msmvps.com linky no worky