O EXCEPT
operador foi introduzido no SQL Server 2005, mas qual é a diferença entre NOT IN
e EXCEPT
?
Faz o mesmo? Eu gostaria de uma explicação simples com um exemplo.
fonte
O EXCEPT
operador foi introduzido no SQL Server 2005, mas qual é a diferença entre NOT IN
e EXCEPT
?
Faz o mesmo? Eu gostaria de uma explicação simples com um exemplo.
Existem duas diferenças principais entre EXCEPT
e NOT IN
.
EXCEPT
filtra os DISTINCT
valores da tabela à esquerda que não aparecem na tabela à direita. É essencialmente o mesmo que fazer a NOT EXISTS
com uma DISTINCT
cláusula.
Ele também espera que as duas tabelas (ou subconjunto de colunas das tabelas) tenham o mesmo número de colunas no lado esquerdo e direito da consulta
Por exemplo, você não pode fazer:
SELECT ID, Name FROM TableA
EXCEPT
SELECT ID FROM TableB
Isso resultaria no erro:
Todas as consultas combinadas usando um operador UNION, INTERSECT ou EXCEPT devem ter um número igual de expressões em suas listas de destino.
NOT IN
não filtra DISTINCT
valores e retorna todos os valores da tabela à esquerda que não aparecem na tabela à direita.
NOT IN
requer que você compare uma única coluna de uma tabela com uma única coluna de outra tabela ou subconsulta.
Por exemplo, se sua subconsulta deveria retornar várias colunas:
SELECT * FROM TableA AS nc
WHERE ID NOT IN (SELECT ID, Name FROM TableB AS ec)
Você receberá o seguinte erro:
Somente uma expressão pode ser especificada na lista de seleção quando a subconsulta não é introduzida com EXISTS.
No entanto, se a tabela à direita contiver um NULL
nos valores que estão sendo filtrados NOT IN
, um conjunto de resultados vazio será retornado, potencialmente fornecendo resultados inesperados.
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)
Das duas consultas acima, EXCEPT
retorna 3 linhas #NewCustomers
, filtrando o 1 e o 3 que correspondem #ExistingCustomers
e o 8 duplicado.
NOT IN
não faz essa filtragem distinta e retorna 4 linhas #NewCustomers
com o 8 duplicado.
Se agora adicionarmos NULL
a à #ExistingCustomers
tabela, veremos os mesmos resultados retornados por EXCEPT
, no entanto NOT IN
, retornará um conjunto de resultados vazio.
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;
Em vez disso NOT IN
, você deve realmente olhar NOT EXISTS
e há uma boa comparação entre os dois no blog de Gail Shaw .
Uma adição ao excelente comentário de Mark Sinkinson:
Na verdade, você pode executar
NOT IN
com mais de uma coluna.Por exemplo, esta é uma consulta SQL * prefectly legal :
Que retornará
first_name
elast_name
de todas as pessoas que são funcionários, mas também não são gerentes.*: mas a construção ainda não foi implementada no SQL Server.
fonte
O NOT IN acima falha porque é necessário haver uma correlação entre os predicados na consulta principal e a subconsulta. Se você deixar de fora, você obtém uma subconsulta NÃO CORRETA.
SELECT * FROM TableA AS nc ONDE ID NÃO ESTÁ (SELECT ID, Nome FROM TableB AS ec onde nc.ID = ec.ID)
EXCEPT é melhor e manipulará qualquer linha nula sem usar os predicados IS NULL / IS NOT NULL.
fonte