SQL NOT IN funktioniert nicht

72

Ich habe zwei Datenbanken, eine mit dem Inventar und eine mit einer Teilmenge der Datensätze der Primärdatenbank.

Die folgende SQL-Anweisung funktioniert nicht:

SELECT  stock.IdStock
        ,stock.Descr       
FROM    [Inventory].[dbo].[Stock] stock
WHERE   stock.IdStock NOT IN
        (SELECT foreignStockId FROM
         [Subset].[dbo].[Products])

Das nicht in funktioniert nicht. Das Entfernen des NOT führt zu den richtigen Ergebnissen, dh Produkten, die sich in beiden Datenbanken befinden. Die Verwendung von NOT IN liefert jedoch überhaupt keine Ergebnisse.

Was mache ich falsch, irgendwelche Ideen?

Sam
quelle
Sind Sie sicher, dass Sie stock.IdStock haben, die überhaupt nicht in ForeignStockId enthalten sind?
CloudyMarble
Haben Sie wirklich Gegenstände Inventory, die nicht in sind Subset?
Albin Sunnanbo
1
Erklären Sie, was die Abfrage zurückgeben soll. Derzeit werden alle Lagerartikel zurückgegeben, bei denen sich kein Produkt in der Teilmenge befindet, die darauf verweist.
Stefan Steinegger

Antworten:

196
SELECT foreignStockId
FROM   [Subset].[dbo].[Products]  

Gibt wahrscheinlich a zurück NULL.

Eine NOT INAbfrage gibt keine Zeilen zurück, wenn in der Werteliste NULLs vorhanden NOT INsind. Sie können sie explizit IS NOT NULLwie folgt ausschließen.

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 NOT EXISTSstattdessen mit.

SELECT stock.idstock,
       stock.descr
FROM   [Inventory].[dbo].[Stock] stock
WHERE  NOT EXISTS (SELECT *
                   FROM   [Subset].[dbo].[Products] p
                   WHERE  p.foreignstockid = stock.idstock) 

Die Semantik, für die Sie den Ausführungsplan wünschen, NOT EXISTSist oft einfacher, als hier dargestellt .

Der Grund für den Unterschied im Verhalten liegt in der dreiwertigen Logik, die in SQL verwendet wird. Prädikate zu bewerten True, Falseoder Unknown.

Eine WHEREKlausel muss ausgewertet werden, Truedamit die Zeile zurückgegeben wird. Dies ist jedoch nicht möglich, NOT INwenn sie NULLvorhanden ist, wie unten erläutert.

'A' NOT IN ('X','Y',NULL) ist äquivalent zu 'A' <> 'X' AND 'A' <> 'Y' AND 'A' <> NULL)

  • 'A' <> 'X' = True
  • 'A' <> 'Y' = True
  • 'A' <> NULL = Unknown

True AND True AND Unknownausgewertet nach Unknownden Wahrheitstabellen für drei wertige Logik .

Die folgenden Links enthalten zusätzliche Informationen zur Leistung der verschiedenen Optionen.

Martin Smith
quelle
Das hat es für mich behoben. Wählen Sie * Von x Wo xy nicht in (Wählen Sie Distinct ISNULL (c, 0))
Spaceman
Oh mein Gott, in der Tat hat select null zurückgegeben und NOT IN hat nicht richtig funktioniert. 6 Jahre später grüße ich Sie
qki
3

Wenn NOT IN nicht funktioniert, können Sie immer versuchen, LEFT JOIN auszuführen . Filtern Sie dann nach WHERE, indem Sie einen der Werte aus der verknüpften Tabelle verwenden, die NULL sind . Vorausgesetzt, der Wert, durch den Sie beigetreten sind, enthält keinen NULL- Wert.

MPękalski
quelle
0

Sie können auch die Case-Klausel verwenden, um solche Probleme zu lösen

SELECT  stock.IdStock
        ,stock.Descr        
FROM    [Inventory].[dbo].[Stock] stock
WHERE   (Case when stock.IdStock IN
        (SELECT foreignStockId FROM
        [Subset].[dbo].[Products]) then 1 else 0 end) = 0 

Diese Syntax funktioniert in SQL Server, Oracle und Postgres

Raj Kamal
quelle
0

Hinzufügen meiner 2 Cent:

Ich habe SQL Server sogar falsche Ergebnisse Rückkehr zu sehen , wenn die Umstellung auf not existsund left join- in korrupten Datenbanken . Führen Sie DBCC CHECKTABLE für die beteiligten Tabellen aus, sehen Sie sich auch den NOT INAbfrageausführungsplan an und erstellen Sie die beteiligten Indizes neu. Dies sollte helfen.

Alex
quelle