SELECT foreignStockId
FROM [Subset].[dbo].[Products]
Prawdopodobnie zwraca NULL
.
NOT IN
zapytanie nie zwróci żadnych wierszy, jeśli jakikolwiek NULL
s istnieje na liście NOT IN
wartości. Możesz je wyraźnie wykluczyć, używając IS NOT NULL
jak poniżej.
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)
Lub przepisz używając NOT EXISTS
zamiast tego.
SELECT stock.idstock,
stock.descr
FROM [Inventory].[dbo].[Stock] stock
WHERE NOT EXISTS (SELECT *
FROM [Subset].[dbo].[Products] p
WHERE p.foreignstockid = stock.idstock)
Oprócz semantyki, którą chcesz, aby plan wykonania dla NOT EXISTS
jest często prostsze, jak pokazano tutaj.
Powodem różnicy w zachowaniu jest trzy wartościowa logika używana w SQL. Predykaty mogą mieć wartość True
, False
lub Unknown
.
WHERE
klauzula musi mieć wartość True
aby wiersz został zwrócony, ale nie jest to możliwe w przypadku NOT IN
kiedy NULL
jest obecny, jak wyjaśniono poniżej.
'A' NOT IN ('X','Y',NULL)
jest odpowiednikiem 'A' <> 'X' AND 'A' <> 'Y' AND 'A' <> NULL)
- „A” <> „X” =
True
- „A” <> „Y” =
True
- 'A' <> NULL =
Unknown
True AND True AND Unknown
ocenia jako Unknown
zgodnie z tabelami prawdy dla trzech wartości logiki.
Poniższe linki zawierają dodatkowe omówienie wydajności różnych opcji.
- Czy powinienem użyć
NOT IN
,OUTER APPLY
,LEFT OUTER JOIN
,EXCEPT
lubNOT EXISTS
? NOT IN
w porównaniu zNOT EXISTS
aLEFT JOIN / IS NULL
:Serwer SQLLeft outer join
vsNOT EXISTS
NOT EXISTS
w porównaniu zNOT IN