I have a table named Product and a table named ProductPropertiesCountry.
Product is the definition of a product (description, price, productId, etc)
ProductPropertiesCountry contains restrictions on the product by country, for example IsBlocked, and attributes such as Special Price.
Product
- ProductId
- Description
- Price
ProductPropertiesCountry
- ProductId (PK)
- CountryId (PK)
- SpecialPrice
- IsBlocked
I'm doing a LEFT JOIN between Product and ProductPropertiesCountry with a WHERE clause like this:
SELECT P.ProductId
FROM Product P
LEFT JOIN ProductPropertiesCountry PPC ON
P.ProductId = PPC.Product AND PPC.CountryID = 1
WHERE (IsBlocked IS NULL OR IsBlocked = 0)
The problem is that the execution plan does not handle IsBlocked IS NULL efficiently and it gives me Estimated number of rows = 1 after that filter. As result, the query is slower.
This is much faster:
;WITH CATALOG
AS
(
SELECT P.ProductId, ISNULL(IsBlocked, 0) AS IsBlocked
FROM Product P
LEFT JOIN ProductPropertiesCountry PPC
ON P.ProductId = PPC.Product AND PPC.CountryID = 1
)
SELECT ProductId, IsBlocked
FROM CATALOG
WHERE IsBlocked = 0;
Do you have any idea for the reason of this behavior?
Any suggestion to change it to get the right estimated number of rows in execution plan?
I'm using SQL Server 2008.

WHERE (IsBlocked IS NULL OR IsBlocked = 0)with thisWhere isnull(IsBlocked,0) = 0– AmmarR Sep 11 '12 at 11:07IsBlocked = 0condition fromWHEREand leaving theWHERE IS NULLpart only. (After all, we are dealing with a left join.) That would still result in a different output. Presently, the queries retrieve Products that have no match in PPC or those that havePPC.IsBlocked = 0. With your suggestion, the results would contain Products that are absent fromPPCor havePPC.IsBlockedother than0. However,ON P.ProductId = PPC.Product AND PPC.CountryID = 1 AND PPC.IsBlocked = 1and leaving theWHERE IS NULLcheck should do the trick. – Andriy M Sep 12 '12 at 6:10