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
oNOT EXISTS
? NOT IN
rispetto aNOT EXISTS
rispetto aLEFT JOIN / IS NULL
:SQL ServerLeft outer join
vsNOT EXISTS
NOT EXISTS
vsNOT IN