SELECT foreignStockId
FROM [Subset].[dbo].[Products]
Returnerar förmodligen en NULL .
En NOT IN fråga kommer inte att returnera några rader om några NULL s finns i listan över NOT IN värden. Du kan uttryckligen exkludera dem med IS NOT NULL enligt nedan.
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)
Eller skriv om med NOT EXISTS istället.
SELECT stock.idstock,
stock.descr
FROM [Inventory].[dbo].[Stock] stock
WHERE NOT EXISTS (SELECT *
FROM [Subset].[dbo].[Products] p
WHERE p.foreignstockid = stock.idstock)
Förutom att ha den semantik som du vill ha exekveringsplanen för NOT EXISTS är ofta enklare som vi ser här.
Anledningen till skillnaden i beteende beror på de tre värderade logiken som används i SQL. Predikat kan utvärderas till True , False , eller Unknown .
En WHERE klausul måste utvärderas till True för att raden ska returneras men detta är inte möjligt med NOT IN när NULL finns som förklarat nedan.
'A' NOT IN ('X','Y',NULL) motsvarar 'A' <> 'X' AND 'A' <> 'Y' AND 'A' <> NULL)
- 'A' <> 'X' =
True - 'A' <> 'Y' =
True - 'A' <> NULL =
Unknown
True AND True AND Unknown utvärderas till Unknown enligt sanningstabellerna för tre värdefulla logik.
Följande länkar har ytterligare diskussioner om hur de olika alternativen fungerar.
- Ska jag använda
NOT IN,OUTER APPLY,LEFT OUTER JOIN,EXCEPT, ellerNOT EXISTS? NOT INkontraNOT EXISTSkontraLEFT JOIN / IS NULL:SQL ServerLeft outer joinkontraNOT EXISTSNOT EXISTSkontraNOT IN