J'ai deux tables avec une clé primaire de liaison dans la base de données et je souhaite trouver un ensemble disjoint entre elles. Par exemple,
Table1
a des colonnes (ID, Name
) et des exemples de données: (1 ,John), (2, Peter), (3, Mary)
Table2
a des colonnes (ID, Address
) et des exemples de données: (1, address2), (2, address2)
Alors, comment puis-je créer une requête SQL afin que je puisse récupérer la ligne avec l'ID de table1
qui n'est pas dans table2
. Dans ce cas, (3, Mary)
devrait être retourné?
Ps. L'ID est la clé primaire de ces deux tables.
Merci d'avance.
Essaye ça
SELECT ID, Name
FROM Table1
WHERE ID NOT IN (SELECT ID FROM Table2)
Utilisez LEFT JOIN
SELECT a.*
FROM table1 a
LEFT JOIN table2 b
on a.ID = b.ID
WHERE b.id IS NULL
J'ai exécuté des tests (sur Postgres 9.5) en utilisant deux tables avec environ 2 millions de lignes chacune. Cette requête ci-dessous a eu au moins 5 * de meilleurs résultats que les autres requêtes proposées:
-- Count
SELECT count(*) FROM (
(SELECT id FROM table1) EXCEPT (SELECT id FROM table2)
) t1_not_in_t2;
-- Get full row
SELECT table1.* FROM (
(SELECT id FROM table1) EXCEPT (SELECT id FROM table2)
) t1_not_in_t2 JOIN table1 ON t1_not_in_t2.id=table1.id;
Gardant à l'esprit les remarques faites dans le commentaire/lien de @ John Woo ci-dessus, voici comment je le gérerais généralement:
SELECT t1.ID, t1.Name
FROM Table1 t1
WHERE NOT EXISTS (
SELECT TOP 1 NULL
FROM Table2 t2
WHERE t1.ID = t2.ID
)
Il existe essentiellement 3 approches pour cela: not exists
, not in
et left join / is null
.
SELECT l.*
FROM t_left l
LEFT JOIN
t_right r
ON r.value = l.value
WHERE r.value IS NULL
SELECT l.*
FROM t_left l
WHERE l.value NOT IN
(
SELECT value
FROM t_right r
)
SELECT l.*
FROM t_left l
WHERE NOT EXISTS
(
SELECT NULL
FROM t_right r
WHERE r.value = l.value
)
Quel est le meilleur? Il serait peut-être préférable de répondre à cette question en fonction des principaux fournisseurs de SGBDR spécifiques. En règle générale, évitez d'utiliser select ... where ... in (select...)
lorsque l'ampleur du nombre d'enregistrements de la sous-requête est inconnue. Certains vendeurs peuvent limiter la taille. Oracle, par exemple, a un limite de 1 0 . La meilleure chose à faire est d'essayer les trois et de montrer le plan d'exécution.
En particulier dans PostgreSQL, le plan d’exécution de NOT EXISTS
et LEFT JOIN / IS NULL
est identique. Personnellement, je préfère l’option NOT EXISTS
car elle montre mieux l’intention. Après toute la sémantique, c’est que vous voulez trouver des enregistrements dans A et que ses pk n’existent pas dans B .
Vieux mais toujours or, spécifique à PostgreSQL cependant: https://explainextended.com/2009/09/16/not-in-vs-not-exists-vs-left-join-is-null-postgresql/
SELECT COUNT(ID) FROM tblA a
WHERE a.ID NOT IN (SELECT b.ID FROM tblB b) --For count
SELECT ID FROM tblA a
WHERE a.ID NOT IN (SELECT b.ID FROM tblB b) --For results