Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

SQL NOT IN funktioniert nicht

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 , oder NOT EXISTS ?
  • NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL :SQL-Server
  • Left outer join vs NOT EXISTS
  • NOT EXISTS vs NOT IN