SQL NOT IN not working

I have two databases, one of which contains inventory, and the other is a subset of the primary database records.

The following SQL statement does not work:

SELECT stock.IdStock ,stock.Descr FROM [Inventory].[dbo].[Stock] stock WHERE stock.IdStock NOT IN (SELECT foreignStockId FROM [Subset].[dbo].[Products]) 

Doesn't work. Removing NOT gives the correct results, that is, products that are in both databases. However, using NOT IN does not return any results.

What am I doing wrong, any ideas?

+49
sql sql-server
Mar 08 '11 at 11:17
source share
2 answers
 SELECT foreignStockId FROM [Subset].[dbo].[Products] 

Probably returns a NULL .

A NOT IN query will not return rows if any NULL exists in the NOT IN list of values. You can explicitly exclude them using IS NOT NULL , as shown below.

 SELECT stock.IdStock, stock.Descr FROM [Inventory].[dbo].[Stock] stock WHERE stock.IdStock NOT IN (SELECT foreignStockId FROM [Subset].[dbo].[Products] WHERE foreignStockId IS NOT NULL) 

Or rewrite using NOT EXISTS .

 SELECT stock.idstock, stock.descr FROM [Inventory].[dbo].[Stock] stock WHERE NOT EXISTS (SELECT * FROM [Subset].[dbo].[Products] p WHERE p.foreignstockid = stock.idstock) 

Besides the semantics you want, the execution plan for NOT EXISTS often simpler as shown here .

The reason for the difference in behavior comes down to the three-valued logic used in SQL. Predicates can be evaluated to True , False or Unknown .

Sentence

A WHERE must be evaluated to True in order for the string to be returned, but this is not possible when using NOT IN when NULL present, as described below.

'A' NOT IN ('X','Y',NULL) equivalent to 'A' <> 'X' AND 'A' <> 'Y' AND 'A' <> NULL)

  • 'A' <> 'X' = True
  • 'A' <> 'Y' = True
  • 'A' <> NULL = Unknown

True AND True AND Unknown ranks Unknown for truth tables for three-valued logic .

The following links provide additional information on the performance of various parameters.

+123
Mar 08 '11 at 11:19
source share

If NOT IN does not work, you can always try to make a LEFT JOIN . Then filter WHERE using one of the values ​​from the joined table that is NULL . Provided that the value you connected to does not contain a NULL value.

+2
Mar 08 2018-11-11T00:
source share



All Articles