¿Cómo seleccionar todos los registros de una tabla que no existen en otra tabla?

470

tabla1 (id, nombre)
tabla2 (id, nombre)

Consulta:

SELECT name   
FROM table2  
-- that are not in table1 already
z-boss
fuente

Respuestas:

844
SELECT t1.name
FROM table1 t1
LEFT JOIN table2 t2 ON t2.name = t1.name
WHERE t2.name IS NULL

P : ¿Qué está pasando aquí?

R : Conceptualmente, seleccionamos todas las filas de table1y para cada fila intentamos encontrar una fila table2con el mismo valor para la namecolumna. Si no existe esa fila, solo dejamos la table2parte de nuestro resultado vacía para esa fila. Luego, restringimos nuestra selección seleccionando solo aquellas filas en el resultado donde la fila coincidente no existe. Finalmente, ignoramos todos los campos de nuestro resultado, excepto la namecolumna (la que estamos seguros de que existe table1).

Si bien puede no ser el método más eficaz posible en todos los casos, debería funcionar básicamente en todos los motores de bases de datos que intentan implementar ANSI 92 SQL

Kris
fuente
16
@ z-boss: También es el de menor rendimiento en SQL Server: explainextended.com/2009/09/15/…
OMG Ponies
77
@BunkerBoy: una unión izquierda permite que las filas de la derecha no existan sin que eso afecte la inclusión de filas de la izquierda. Una unión interna requiere filas a la izquierda y a la derecha para estar presentes. Lo que estoy haciendo aquí es aplicar algo de lógica para obtener básicamente la selección inversa de una unión interna.
Kris
2
Dios mío, esto ayudó a visualizar muy fácilmente, otros lo habían dicho de 5 maneras diferentes, pero esto ayudó. simple: primero te unes a la izquierda, todo en A y todo en B que coincide con A. Pero como sucede en los campos de unión a la izquierda que no se unen, son nulos. Entonces dices, ok, solo quiero que sean nulos. De esta forma, ahora tiene todas las filas en A que no tenían una coincidencia En B
Muhammad Umer
77
Cabe señalar que esta solución (aceptada y votada) es la única, creo, podría editarse para un escenario en el que entra en juego más de un campo. Específicamente, estoy devolviendo el campo, campo 2, campo 3 de la tabla uno donde la combinación de campo y campo2 no está en la segunda tabla. Aparte de modificar la combinación en esta respuesta, no veo una manera de hacerlo con algunas de las otras "respuestas más eficientes" que se
detallan
1
Solo asegúrese de usar "WHERE t2.name IS NULL" y no "AND t2.name IS NULL" porque "y" no darán los resultados correctos. Realmente no entiendo por qué, pero es un hecho, lo probé.
user890332
236

Puedes hacer

SELECT name
FROM table2
WHERE name NOT IN
    (SELECT name 
     FROM table1)

o

SELECT name 
FROM table2 
WHERE NOT EXISTS 
    (SELECT * 
     FROM table1 
     WHERE table1.name = table2.name)

Vea esta pregunta para 3 técnicas para lograr esto

froadie
fuente
38
Esto es increíblemente lento con grandes cantidades de datos.
Bombilla1
Sí, de hecho es muy lento
sirus
¿No debería ser "from table1" en la subconsulta de la consulta no existe.
Hound
Muy confundido sobre cómo esto obtuvo tantos votos positivos. Me resulta muy difícil pensar en una razón para usar esto, cuando hay un enfoque para este problema que es increíblemente más rápido con aproximadamente el mismo número de pulsaciones de teclas.
searchengine27
Este funcionó para mí ... Gracias
Thameem
81

No tengo suficientes puntos de representante para votar la segunda respuesta. Pero tengo que estar en desacuerdo con los comentarios en la respuesta superior. La segunda respuesta:

SELECT name
FROM table2
WHERE name NOT IN
    (SELECT name 
     FROM table1)

Es MUCHO más eficiente en la práctica. No sé por qué, pero lo estoy ejecutando con más de 800k de registros y la diferencia es tremenda con la ventaja dada a la segunda respuesta publicada anteriormente. Solo mis $ 0.02

Tan Rezaei
fuente
31
En la consulta NOT IN, la subconsulta se realiza solo una vez, en la consulta EXISTS, la subconsulta se realiza para cada fila
Carrick
2
eres increíble :) de esta manera convierto mi consulta de 25 segundos usando la combinación izquierda a solo 0.1 segundos
Bassem Shahin
3
las respuestas no están en ningún orden específico, por lo que la segunda respuesta no significa lo que pensabas que significaba.
38

Esta es la teoría de conjuntos pura que puede lograr con la minusoperación.

select id, name from table1
minus
select id, name from table2
Invierno
fuente
¿Crees que esto es mucho más eficiente que dejar unirse?
Uhs
Debería ser. El comando menos está diseñado para esta situación exacta. Por supuesto, la única forma de juzgar cualquier conjunto de datos en particular es probarlo en ambos sentidos y ver cuál funciona más rápido.
Invierno
99
En T-SQL, el operador de conjunto es "excepto". Esto es muy conveniente para mí y no ha causado ninguna desaceleración.
2
En SQLite, el operador "menos" también es "excepto".
Lifjoy
MySQL no es compatible con el operador MINUS.
Muhammad Azeem
16

Cuidado con las trampas. Si el campo Namede Table1contener valores nulos usted está en para sorpresas. Mejor es:

SELECT name
FROM table2
WHERE name NOT IN
    (SELECT ISNULL(name ,'')
     FROM table1)
usuario4872693
fuente
1
COALESCE> ISNULL (ISNULL es una adición inútil de T-SQL al lenguaje que no hace nada nuevo o mejor que COALESCE)
Kris
14

Esto es lo que funcionó mejor para mí.

SELECT *
FROM @T1
EXCEPT
SELECT a.*
FROM @T1 a
JOIN @T2 b ON a.ID = b.ID

Esto fue más del doble de rápido que cualquier otro método que probé.

Beto
fuente
¡Gracias, esto funciona bien con una gran cantidad de datos también! Pero me pregunto sobre el término 'Excepto'.
PatsonLeaner
7

Ese trabajo fuerte para mi

SELECT * 
FROM [dbo].[table1] t1
LEFT JOIN [dbo].[table2] t2 ON t1.[t1_ID] = t2.[t2_ID]
WHERE t2.[t2_ID] IS NULL
David Fawzy
fuente
1

Ver consulta:

SELECT * FROM Table1 WHERE
id NOT IN (SELECT 
        e.id
    FROM
        Table1 e
            INNER JOIN
        Table2 s ON e.id = s.id);

Conceptualmente sería: Obtener los registros coincidentes en la subconsulta y luego en la consulta principal recuperar los registros que no están en la subconsulta.

jawahar
fuente
0

Voy a volver a publicar (ya que todavía no soy lo suficientemente bueno como para comentar) en la respuesta correcta ... en caso de que alguien más pensara que necesitaba una mejor explicación.

SELECT temp_table_1.name
FROM original_table_1 temp_table_1
LEFT JOIN original_table_2 temp_table_2 ON temp_table_2.name = temp_table_1.name
WHERE temp_table_2.name IS NULL

Y he visto la sintaxis en FROM que necesita comas entre los nombres de las tablas en mySQL pero en sqlLite parecía preferir el espacio.

La conclusión es que cuando usas nombres de variables incorrectos, deja preguntas. Mis variables deberían tener más sentido. Y alguien debería explicar por qué necesitamos una coma o ninguna coma.

Adrian Roth
fuente
0

Si quieres seleccionar en usuario específico

SELECT tent_nmr FROM Statio_Tentative_Mstr
WHERE tent_npk = '90009'
AND
tent_nmr NOT IN (SELECT permintaan_tent FROM Statio_Permintaan_Mstr)

La tent_npkes una clave principal de un usuario

Fragmantedbin
fuente