Consider the following two queries from the AdventureWorks database. The where criteria is entirely on indexed columns. If you use OR criteria both tables get a full table scan on them. In the second scenario the criteria is split out over two queries that are unioned. In the second scenario both tables get index seeks. Can someone explain why SQL can't/won't optimize the first query to do an index seek? Are there ways to tell SQL to do a seek without rewriting as a UNION? (I've tried index hints with no success)
SELECT *
FROM [AdventureWorks2022].[Sales].[SalesOrderHeader] hdr
JOIN [AdventureWorks2022].[Sales].[SalesOrderDetail] dtl ON hdr.SalesOrderID = dtl.SalesOrderID
WHERE hdr.SalesOrderID = 43659 OR dtl.SalesOrderDetailID = 43659
----
SELECT *
FROM [AdventureWorks2022].[Sales].[SalesOrderHeader] hdr
JOIN [AdventureWorks2022].[Sales].[SalesOrderDetail] dtl ON hdr.SalesOrderID = dtl.SalesOrderID
WHERE hdr.SalesOrderID = 43659
UNION
SELECT *
FROM [AdventureWorks2022].[Sales].[SalesOrderHeader] hdr
JOIN [AdventureWorks2022].[Sales].[SalesOrderDetail] dtl ON hdr.SalesOrderID = dtl.SalesOrderID
WHERE dtl.SalesOrderDetailID = 43659
This answer by Paul White seems to explain it and confirms that SQL cannot come up with the UNION
plan with the OR
criteria.
This transform only applies to a single table, and does not apply to attribute-to-attribute comparisons.