SELECT foreignStockId
FROM [Subset].[dbo].[Products]
Gibt wahrscheinlich ein NULL
zurück .
A NOT IN
Die Abfrage gibt keine Zeilen zurück, wenn NULL
vorhanden ist s existiert in der Liste NOT IN
Werte. Sie können sie explizit mit IS NOT NULL
ausschließen wie unten.
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)
Oder schreiben Sie mit NOT EXISTS
um stattdessen.
SELECT stock.idstock,
stock.descr
FROM [Inventory].[dbo].[Stock] stock
WHERE NOT EXISTS (SELECT *
FROM [Subset].[dbo].[Products] p
WHERE p.foreignstockid = stock.idstock)
Sowie die Semantik, dass Sie den Ausführungsplan für NOT EXISTS
haben möchten ist oft einfacher als hier zu sehen.
Der Grund für das unterschiedliche Verhalten liegt in der dreiwertigen Logik, die in SQL verwendet wird. Prädikate können als True
ausgewertet werden , False
, oder Unknown
.
Ein WHERE
-Klausel muss zu True
ausgewertet werden damit die Zeile zurückgegeben wird, was aber mit NOT IN
nicht möglich ist wenn NULL
vorhanden ist, wie unten erklärt.
'A' NOT IN ('X','Y',NULL)
entspricht 'A' <> 'X' AND 'A' <> 'Y' AND 'A' <> NULL)
- 'A' <> 'X' =
True
- 'A' <> 'Y' =
True
- 'A' <> NULL =
Unknown
True AND True AND Unknown
wird zu Unknown
ausgewertet nach den Wahrheitstabellen für dreiwertige Logik.
Die folgenden Links enthalten zusätzliche Diskussionen über die Leistung der verschiedenen Optionen.
- Soll ich
NOT IN
verwenden ,OUTER APPLY
,LEFT OUTER JOIN
,EXCEPT
, oderNOT EXISTS
? NOT IN
vs.NOT EXISTS
vs.LEFT JOIN / IS NULL
:SQL-ServerLeft outer join
vsNOT EXISTS
NOT EXISTS
vsNOT IN