Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

SQL NOT IN non funziona

SELECT foreignStockId
FROM   [Subset].[dbo].[Products]  

Probabilmente restituisce un NULL .

Un NOT IN query non restituirà alcuna riga se qualsiasi NULL s esiste nell'elenco di NOT IN valori. Puoi escluderli esplicitamente usando IS NOT NULL come di seguito.

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) 

Oppure riscrivi usando NOT EXISTS invece.

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

Oltre ad avere la semantica che desideri il piano di esecuzione per NOT EXISTS è spesso più semplice come visto qui.

Il motivo della differenza di comportamento è dovuto alla logica a tre valori utilizzata in SQL. I predicati possono restituire True , False o Unknown .

Un WHERE la clausola deve restituire True affinché la riga venga restituita ma ciò non è possibile con NOT IN quando NULL è presente come spiegato di seguito.

'A' NOT IN ('X','Y',NULL) è equivalente a 'A' <> 'X' AND 'A' <> 'Y' AND 'A' <> NULL)

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

True AND True AND Unknown restituisce Unknown per le tavole di verità per tre valori logici.

I seguenti collegamenti contengono ulteriori discussioni sulle prestazioni delle varie opzioni.

  • Dovrei usare NOT IN , OUTER APPLY , LEFT OUTER JOIN , EXCEPT o NOT EXISTS ?
  • NOT IN rispetto a NOT EXISTS rispetto a LEFT JOIN / IS NULL :SQL Server
  • Left outer join vs NOT EXISTS
  • NOT EXISTS vs NOT IN