Mysql: seleccione filas de una tabla que no están en otra

118

¿Cómo seleccionar todas las filas de una tabla que no aparecen en otra?

Tabla 1:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Tia       | Carrera  | 1975-09-18 |
| Nikki     | Taylor   | 1972-03-04 |
| Yamila    | Diaz     | 1972-03-04 |
+-----------+----------+------------+

Tabla 2:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Tia       | Carrera  | 1975-09-18 |
| Nikki     | Taylor   | 1972-03-04 |
+-----------+----------+------------+

Salida de ejemplo para filas en Table1 que no están en Table2:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Yamila    | Diaz     | 1972-03-04 |
+-----------+----------+------------+

Quizás algo como esto debería funcionar:

SELECT * FROM Table1 WHERE * NOT IN (SELECT * FROM Table2)
Christopher Rapcewicz
fuente

Respuestas:

96

Si tiene 300 columnas como mencionó en otro comentario y desea comparar todas las columnas (asumiendo que todas las columnas tienen el mismo nombre), puede usar a NATURAL LEFT JOINpara unir implícitamente todos los nombres de columna coincidentes entre las dos tablas para que pueda no tiene que escribir tediosamente todas las condiciones de unión manualmente:

SELECT            a.*
FROM              tbl_1 a
NATURAL LEFT JOIN tbl_2 b
WHERE             b.FirstName IS NULL
Zane Bien
fuente
Tenga en cuenta que esto solo funciona como se esperaba cuando ninguna de las columnas tiene valores NULL. En MySQL NULL! = NULL, por lo que cada fila que tenga un valor NULL se devolverá incluso si hay una fila duplicada en la segunda tabla.
Kyle Kochis
84
Si tiene 300 columnas, debe rediseñar su base de datos.
Iharob Al Asimi
oye, esto también funciona para mí, ¡gracias! pero, ¿sería un problema si las filas son> 300 como mencionaste anteriormente?
thekucays
todavía estoy confundido acerca de la consulta por cierto ... ¿qué pasa si cambio "donde b.FirstName es nulo" a "donde b.LastName es nulo", por ejemplo? ¿cual es la diferencia? Lo siento por preguntar esto, todavía soy nuevo en sql: D
thekucays
184

Debe realizar la subselección según el nombre de una columna, no *.

Por ejemplo, si tuviera un idcampo común a ambas tablas, podría hacer:

SELECT * FROM Table1 WHERE id NOT IN (SELECT id FROM Table2)

Consulte la sintaxis de la subconsulta de MySQL para obtener más ejemplos.

Stennie
fuente
1
¡gracias por la aclaración! pero realmente no necesito basar la selección de filas en ningún campo, porque estoy interesado en cualquier variación de cualquier campo en la fila ...
Si solo hay unas pocas columnas para comparar, puede unirse como en el ejemplo de @ Steve. Si en realidad está solicitando una comparación general de datos en dos tablas con muchas columnas, probablemente desee buscar una herramienta de diferencias de MySQL .
Stennie
2
Tenga en cuenta que esto siempre devolverá un conjunto vacío si la columna que está mirando en la Tabla2 contiene nulos. No es un problema si lo hace en función de la clave principal, pero es relevante para las personas que intentan utilizar esta consulta en otros contextos.
Mark Amery
4
Pero, ¿y si hablamos de big data? ¿Y Table2 contiene 100 millones de filas, por ejemplo?
Abierto
Respuesta inteligente e inteligente. Gracias compañero
Anjana Silva
44
SELECT *
FROM Table1 AS a
WHERE NOT EXISTS (
  SELECT *
  FROM Table2 AS b 
  WHERE a.FirstName=b.FirstName AND a.LastName=b.Last_Name
)

EXISTS Te ayudará...

Ruzbeh Irani
fuente
2
Buena respuesta, económica para grandes conjuntos de datos, gracias.
ekerner
Fuerte. La mejor respuesta para grandes conjuntos de datos
Ian Chadwick
35

Una LEFT JOIN estándar podría resolver el problema y, si los campos en la combinación están indexados,
también debería ser más rápido

SELECT *
FROM Table1 as t1 LEFT JOIN Table2 as t2 
ON t1.FirstName = t2.FirstName AND t1.LastName=t2.LastName
WHERE t2.BirthDate Is Null
Steve
fuente
bien, supongo que debe ser así, por cierto, ¿por qué en WHERE t2.Birthdate Is Nulllugar de AND t1.Birthdate = t2.Birthdate?
Porque si agrega eso, entonces se devolverán todas las filas, dice que en la salida deben aparecer solo las filas que no están en la segunda tabla
Steve
1
Esta es una excelente respuesta, ya que no requiere devolver todas las filas de Table2!
dotancohen
Estoy de acuerdo, gran respuesta. Tengo una tabla man-many entre 4 tablas, poner el AND en la unión interna definitivamente va a ser más económico.
DR.
6

Tratar:

SELECT * FROM table1
    LEFT OUTER JOIN table2
    ON table1.FirstName = table2.FirstName and table1.LastName=table2.LastName
    WHERE table2.BirthDate IS NULL
Sachin Pundir
fuente
4

Prueba esta sencilla consulta. Funciona perfectamente.

select * from Table1 where (FirstName,LastName,BirthDate) not in (select * from Table2);
Vijesh
fuente
-3

Esto funcionó para mí en Oracle:

SELECT a.* 
    FROM tbl1 a 
MINUS 
SELECT b.* 
    FROM tbl2 b;
Gennady Sorochan
fuente
La pregunta era sobre MySQL.
jelder
-6
SELECT a.* FROM 
FROM tbl_1 a
MINUS
SELECT b.* FROM 
FROM tbl_2 b
Ingrid R. Forsale
fuente