EXCEPT operator vs NOT IN


Risposte:


29

Esistono due differenze chiave tra EXCEPTe NOT IN.

EXCEPT

EXCEPTfiltra i DISTINCTvalori dalla tabella di sinistra che non compaiono nella tabella di destra. È essenzialmente lo stesso di fare un NOT EXISTScon una DISTINCTclausola.

Si aspetta inoltre che le due tabelle (o sottoinsieme di colonne dalle tabelle) abbiano lo stesso numero di colonne nella parte sinistra e destra della query

Ad esempio, non puoi fare:

SELECT ID, Name FROM TableA
EXCEPT
SELECT ID FROM TableB

Ciò comporterebbe l'errore:

Tutte le query combinate utilizzando un operatore UNION, INTERSECT o EXCEPT devono avere un numero uguale di espressioni nei loro elenchi di destinazione.

NON IN

NOT INnon filtra i DISTINCTvalori e restituisce tutti i valori della tabella di sinistra che non compaiono nella tabella di destra.

NOT IN richiede di confrontare una singola colonna di una tabella con una singola colonna di un'altra tabella o subquery.

Ad esempio, se la tua sottoquery dovesse restituire più colonne:

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

Si otterrebbe il seguente errore:

È possibile specificare solo un'espressione nell'elenco di selezione quando la sottoquery non viene introdotta con EXISTS.

Tuttavia, se la tabella di destra contiene a NULLnei valori da filtrare NOT IN, viene restituito un set di risultati vuoto, che fornisce potenzialmente risultati imprevisti.

ESEMPIO

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)

Dalle due query precedenti, EXCEPTrestituisce 3 righe da #NewCustomers, filtrando 1 e 3 corrispondenti #ExistingCustomerse 8 duplicati.

NOT INnon esegue questo filtro distinto e restituisce 4 righe da #NewCustomerscon il duplicato 8.

Se ora aggiungiamo a NULLalla #ExistingCustomerstabella, vedremo gli stessi risultati restituiti da EXCEPT, tuttavia NOT INverrà restituito un set di risultati vuoto.

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;

Invece NOT IN, dovresti davvero guardare NOT EXISTSe c'è un buon confronto tra i due sul blog di Gail Shaw .


EXCEPT utilizzerà gli indici se appropriato?
JohnOpincar il

1

Un'aggiunta all'eccellente commento di Mark Sinkinson:

NOT IN richiede di confrontare una singola colonna di una tabella con una singola colonna di un'altra tabella o subquery.

In realtà, puoi esibirti NOT INcon più di una colonna.
Ad esempio, questa è una query SQL * perfettamente legale :

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)

Che tornerà first_namee last_namedi tutte le persone che sono dipendenti, ma non sono anche manager.

*: ma la costruzione non è ancora implementata in SQL Server.


-2

NOT IN sopra non riesce perché è necessario che vi sia una correlazione tra i predicati nella query principale e la query secondaria. Se lo lasci fuori, otterrai una sottoquery NON CORRELATA.

SELEZIONA * DA Tabella A COME nc DOVE ID NON IN (SELEZIONA ID, Nome DA Tabella B COME ec dove nc.ID = ec.ID)

EXCEPT è migliore e gestirà le righe null senza utilizzare i predicati IS NULL / IS NOT NULL.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.