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 IN
kontraNOT EXISTS
kontraLEFT JOIN / IS NULL
:SQL ServerLeft outer join
kontraNOT EXISTS
NOT EXISTS
kontraNOT IN