El EXCEPToperador se introdujo en SQL Server 2005, pero ¿cuál es la diferencia entre NOT INy EXCEPT?
¿Hace lo mismo? Me gustaría una explicación simple con un ejemplo.
fuente
El EXCEPToperador se introdujo en SQL Server 2005, pero ¿cuál es la diferencia entre NOT INy EXCEPT?
¿Hace lo mismo? Me gustaría una explicación simple con un ejemplo.
Hay dos diferencias clave entre EXCEPTy NOT IN.
EXCEPTfiltra los DISTINCTvalores de la tabla de la izquierda que no aparecen en la tabla de la derecha. Es esencialmente lo mismo que hacer un NOT EXISTScon una DISTINCTcláusula.
También espera que las dos tablas (o subconjunto de columnas de las tablas) tengan el mismo número de columnas en el lado izquierdo y derecho de la consulta
Por ejemplo, no puedes hacer:
SELECT ID, Name FROM TableA
EXCEPT
SELECT ID FROM TableB
Esto provocaría el error:
Todas las consultas combinadas con un operador UNION, INTERSECT o EXCEPT deben tener el mismo número de expresiones en sus listas de destino.
NOT INno filtra los DISTINCTvalores y devuelve todos los valores de la tabla de la izquierda que no aparecen en la tabla de la derecha.
NOT IN requiere que compare una sola columna de una tabla con una sola columna de otra tabla o subconsulta.
Por ejemplo, si su subconsulta debía devolver varias columnas:
SELECT * FROM TableA AS nc
WHERE ID NOT IN (SELECT ID, Name FROM TableB AS ec)
Obtendría el siguiente error:
Solo se puede especificar una expresión en la lista de selección cuando la subconsulta no se introduce con EXISTS.
Sin embargo, si la tabla de la derecha contiene a NULLen los valores que se filtran NOT IN, se devuelve un conjunto de resultados vacío, lo que puede dar 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)
De las dos consultas anteriores, EXCEPTdevuelve 3 filas de #NewCustomers, filtrando el 1 y 3 que coinciden #ExistingCustomersy el duplicado 8.
NOT INno realiza este filtrado distinto y devuelve 4 filas #NewCustomerscon el duplicado 8.
Si ahora agregamos un NULLa la #ExistingCustomerstabla, vemos los mismos resultados devueltos por EXCEPT, sin embargo NOT IN, devolverá un conjunto de resultados vacío.
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;
En lugar de eso NOT IN, realmente deberías mirar NOT EXISTSy hay una buena comparación entre los dos en el blog de Gail Shaw .
Una adición al excelente comentario de Mark Sinkinson:
En realidad, puede actuar
NOT INcon más de una columna.Por ejemplo, esta es una consulta SQL * perfectamente legal :
Que volverá
first_nameylast_namede todas las personas que son empleados, pero no son también gerentes.*: pero la construcción aún no está implementada en SQL Server.
fuente
El NOT IN anterior falla porque debe haber una correlación entre los predicados en la consulta principal y la subconsulta. Si lo deja fuera, obtiene una subconsulta SIN CORREGIR.
SELECT * FROM TableA AS nc WHERE ID NOT IN (SELECT ID, Name FROM TableB AS ec donde nc.ID = ec.ID)
EXCEPTO es mejor y manejará cualquier fila nula sin usar predicados IS NULL / IS NOT NULL.
fuente