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,EXCEPTlubNOT EXISTS? NOT INw porównaniu zNOT EXISTSaLEFT JOIN / IS NULL:Serwer SQLLeft outer joinvsNOT EXISTSNOT EXISTSw porównaniu zNOT IN