EXCEPT-Operator vs NICHT IN


Antworten:


29

Es gibt zwei Hauptunterschiede zwischen EXCEPTund NOT IN.

AUSSER

EXCEPTfiltert die DISTINCTWerte aus der linken Tabelle, die nicht in der rechten Tabelle erscheinen. Es ist im Grunde dasselbe wie NOT EXISTSmit einer DISTINCTKlausel.

Es wird auch erwartet, dass die beiden Tabellen (oder eine Teilmenge von Spalten aus den Tabellen) links und rechts der Abfrage dieselbe Anzahl von Spalten aufweisen

Zum Beispiel können Sie nicht tun:

SELECT ID, Name FROM TableA
EXCEPT
SELECT ID FROM TableB

Dies würde zu folgendem Fehler führen:

Alle Abfragen, die mit einem UNION-, INTERSECT- oder EXCEPT-Operator kombiniert werden, müssen die gleiche Anzahl von Ausdrücken in ihren Ziellisten enthalten.

NICHT IN

NOT INfiltert nicht nach DISTINCTWerten und gibt alle Werte aus der linken Tabelle zurück, die nicht in der rechten Tabelle enthalten sind.

NOT IN erfordert, dass Sie eine einzelne Spalte aus einer Tabelle mit einer einzelnen Spalte aus einer anderen Tabelle oder Unterabfrage vergleichen.

Wenn Ihre Unterabfrage beispielsweise mehrere Spalten zurückgeben soll:

SELECT * FROM TableA AS nc
WHERE ID NOT IN (SELECT ID, Name FROM TableB AS ec)

Sie würden den folgenden Fehler erhalten:

In der Auswahlliste kann nur ein Ausdruck angegeben werden, wenn die Unterabfrage nicht mit EXISTS eingeführt wird.

Wenn die rechte Tabelle jedoch ein NULLin den Werten enthält, nach denen gefiltert wird NOT IN, wird eine leere Ergebnismenge zurückgegeben, die möglicherweise zu unerwarteten Ergebnissen führt.

BEISPIEL

CREATE TABLE #NewCustomers (ID INT);
CREATE TABLE #ExistingCustomers (ID INT);

INSERT INTO #NewCustomers
        ( ID )
VALUES
     (8), (9), (10), (1), (3), (8);

INSERT INTO #ExistingCustomers
        ( ID )
VALUES
        ( 1) , (2), (3), (4), (5);


-- EXCEPT filters for DISTINCT values
SELECT * FROM #NewCustomers AS nc
EXCEPT
SELECT * FROM #ExistingCustomers AS ec

-- NOT IN returns all values without filtering
SELECT * FROM #NewCustomers AS nc
WHERE ID NOT IN (SELECT ID FROM #ExistingCustomers AS ec)

Gibt aus den beiden obigen Abfragen EXCEPT3 Zeilen zurück #NewCustomers, wobei die übereinstimmenden 1 und 3 #ExistingCustomerssowie das Duplikat 8 herausgefiltert werden.

NOT INführt diese eindeutige Filterung nicht durch und gibt 4 Zeilen #NewCustomersmit dem Duplikat 8 zurück.

Wenn wir jetzt a NULLzur #ExistingCustomersTabelle hinzufügen , sehen wir die gleichen Ergebnisse, die von zurückgegeben wurden EXCEPT, es NOT INwird jedoch eine leere Ergebnismenge zurückgegeben.

INSERT INTO #ExistingCustomers
        ( ID )
VALUES
        ( NULL );

-- With NULL values in the right-hand table, EXCEPT still returns the same results as above
SELECT * FROM #NewCustomers AS nc
EXCEPT
SELECT * FROM #ExistingCustomers AS ec

-- NOT IN now returns no results
SELECT * FROM #NewCustomers AS nc
WHERE ID NOT IN (SELECT ID FROM #ExistingCustomers AS ec)

DROP TABLE #NewCustomers;
DROP TABLE #ExistingCustomers;

Stattdessen NOT INsolltest du dir das wirklich ansehen NOT EXISTSund es gibt einen guten Vergleich zwischen den beiden auf Gail Shaws Blog .


Wird EXCEPT gegebenenfalls Indizes verwenden?
JohnOpincar

1

Eine Ergänzung zu Mark Sinkinsons ausgezeichnetem Kommentar:

NOT IN erfordert, dass Sie eine einzelne Spalte aus einer Tabelle mit einer einzelnen Spalte aus einer anderen Tabelle oder Unterabfrage vergleichen.

Sie können tatsächlich NOT INmit mehr als einer Spalte arbeiten.
Dies ist zB eine vollkommen legale * SQL-Abfrage:

SELECT  E.first_name, E.last_name
FROM    employees E
WHERE   (E.first_name, E.last_name) NOT IN 
              (SELECT M.first_name, M.last_name FROM managers M)

Welches zurückkehren wird first_nameund last_nameausgerechnet Leute, die Angestellte sind, aber nicht auch Manager.

*: aber die Konstruktion ist noch nicht in SQL Server implementiert.


-2

Das oben stehende NOT IN schlägt fehl, da eine Korrelation zwischen den Prädikaten in der Hauptabfrage und der Unterabfrage bestehen muss. Wenn Sie es weglassen, erhalten Sie eine UNKORRELIERTE Unterabfrage.

SELECT * FROM TableA AS nc WHERE ID NICHT IN (SELECT ID, Name FROM TableB AS ec wobei nc.ID = ec.ID)

EXCEPT ist besser und behandelt alle Nullzeilen, ohne IS NULL / IS NOT NULL-Prädikate zu verwenden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.