L' EXCEPT
operatore è stato introdotto in SQL Server 2005 ma qual è la differenza tra NOT IN
e EXCEPT
?
Fa lo stesso? Vorrei una semplice spiegazione con un esempio.
L' EXCEPT
operatore è stato introdotto in SQL Server 2005 ma qual è la differenza tra NOT IN
e EXCEPT
?
Fa lo stesso? Vorrei una semplice spiegazione con un esempio.
Risposte:
Esistono due differenze chiave tra EXCEPT
e NOT IN
.
EXCEPT
filtra i DISTINCT
valori dalla tabella di sinistra che non compaiono nella tabella di destra. È essenzialmente lo stesso di fare un NOT EXISTS
con una DISTINCT
clausola.
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.
NOT IN
non filtra i DISTINCT
valori 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 NULL
nei valori da filtrare NOT IN
, viene restituito un set di risultati vuoto, che fornisce potenzialmente risultati imprevisti.
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, EXCEPT
restituisce 3 righe da #NewCustomers
, filtrando 1 e 3 corrispondenti #ExistingCustomers
e 8 duplicati.
NOT IN
non esegue questo filtro distinto e restituisce 4 righe da #NewCustomers
con il duplicato 8.
Se ora aggiungiamo a NULL
alla #ExistingCustomers
tabella, vedremo gli stessi risultati restituiti da EXCEPT
, tuttavia NOT IN
verrà 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 EXISTS
e c'è un buon confronto tra i due sul blog di Gail Shaw .
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 IN
con 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_name
e last_name
di tutte le persone che sono dipendenti, ma non sono anche manager.
*: ma la costruzione non è ancora implementata in SQL Server.
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.