Mysql: sélectionnez les lignes d'une table qui ne sont pas dans une autre


118

Comment sélectionner toutes les lignes d'une table qui n'apparaissent pas sur une autre?

Tableau 1:

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

Tableau 2:

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

Exemple de sortie pour les lignes de Table1 qui ne sont pas dans Table2:

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

Peut-être que quelque chose comme ça devrait fonctionner:

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

Réponses:


96

Si vous avez 300 colonnes comme vous l'avez mentionné dans un autre commentaire, et que vous souhaitez comparer sur toutes les colonnes (en supposant que les colonnes ont toutes le même nom), vous pouvez utiliser a NATURAL LEFT JOINpour joindre implicitement tous les noms de colonne correspondants entre les deux tables afin que vous pas besoin de taper fastidieusement toutes les conditions de jointure manuellement:

SELECT            a.*
FROM              tbl_1 a
NATURAL LEFT JOIN tbl_2 b
WHERE             b.FirstName IS NULL

Notez que cela ne fonctionne comme prévu que lorsqu'aucune des colonnes n'a de valeurs NULL. Dans MySQL NULL! = NULL donc chaque ligne qui a une valeur NULL sera retournée même s'il y a une ligne en double dans la deuxième table.
Kyle Kochis

84
Si vous avez 300 colonnes, vous devez repenser votre base de données.
Iharob Al Asimi

hé cela fonctionne pour moi aussi, merci! mais serait-ce un problème si les lignes sont> 300 comme vous l'avez mentionné ci-dessus?
thekucays

Je suis toujours confus au sujet de la requête btw.. et si je change "où b.FirstName est nul" en "où b.LastName est nul" par exemple? quelle est la différence? Je suis désolé d'avoir posé cette question, je suis encore nouveau sur sql: D
thekucays

184

Vous devez effectuer la sous-sélection en fonction d'un nom de colonne, pas *.

Par exemple, si vous aviez un idchamp commun aux deux tables, vous pourriez faire:

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

Reportez-vous à la syntaxe de la sous-requête MySQL pour plus d'exemples.


1
Merci pour la clarification! mais je n'ai vraiment pas besoin de baser la sélection de lignes sur un champ, car je suis intéressé par toute variation de n'importe quel champ de la ligne ...

S'il n'y a que quelques colonnes à comparer, vous pouvez effectuer une jointure selon l'exemple de @ Steve. Si vous demandez en fait une comparaison générale des données dans deux tables avec de nombreuses colonnes, vous voudrez probablement chercher un outil de comparaison MySQL .
Stennie

2
Notez que cela renverra toujours un ensemble vide si la colonne que vous regardez dans Table2 contient des valeurs nulles. Ce n'est pas un problème si vous le faites en fonction de la clé primaire, mais pertinent pour les personnes qui essaient d'utiliser cette requête dans d'autres contextes.
Mark Amery

4
Mais que faire si nous parlons de big data? Et Table2 contient 100 millions de lignes, par exemple?
frops

Réponse intelligente et intelligente. Merci mate
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 va vous aider...


2
Bonne réponse, économique pour les grands ensembles de données, merci.
ekerner

Fort. Meilleure réponse pour les grands ensembles de données
Ian Chadwick

35

Une jointure gauche standard pourrait résoudre le problème et, si les champs de jointure sont indexés,
devrait également être plus rapide

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

d'accord, je suppose que ça doit être ça, btw pourquoi la WHERE t2.Birthdate Is Nullplace de AND t1.Birthdate = t2.Birthdate?

Parce que si vous ajoutez cela, alors chaque ligne sera renvoyée, vous dites que dans la sortie ne devrait apparaître que les lignes non dans le deuxième tableau
Steve

1
C'est une réponse formidable, car elle ne nécessite pas de retourner toutes les lignes de Table2!
dotancohen

Je suis d'accord, excellente réponse. J'ai une table man-many entre 4 tables, mettre le AND dans la jointure intérieure va certainement être plus économique.
DR.

6

Essayer:

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

4

Essayez cette simple requête. Cela fonctionne parfaitement.

select * from Table1 where (FirstName,LastName,BirthDate) not in (select * from Table2);


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.