PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Sélectionnez les lignes qui ne sont pas présentes dans une autre table

Il existe essentiellement 4 techniques pour cette tâche, toutes en SQL standard.

NOT EXISTS

Souvent le plus rapide dans Postgres.

SELECT ip 
FROM   login_log l 
WHERE  NOT EXISTS (
   SELECT  -- SELECT list mostly irrelevant; can just be empty in Postgres
   FROM   ip_location
   WHERE  ip = l.ip
   );

Considérez également :

  • Qu'est-ce qui est le plus facile à lire dans les sous-requêtes EXISTS ?

LEFT JOIN / IS NULL

Parfois, c'est le plus rapide. Souvent le plus court. Donne souvent le même plan de requête que NOT EXISTS .

SELECT l.ip 
FROM   login_log l 
LEFT   JOIN ip_location i USING (ip)  -- short for: ON i.ip = l.ip
WHERE  i.ip IS NULL;

EXCEPT

Court. Pas aussi facilement intégré dans des requêtes plus complexes.

SELECT ip 
FROM   login_log

EXCEPT ALL  -- "ALL" keeps duplicates and makes it faster
SELECT ip
FROM   ip_location;

Notez que (selon la documentation) :

les doublons sont éliminés sauf si EXCEPT ALL est utilisé.

En règle générale, vous voudrez le ALL mot-clé. Si vous ne vous en souciez pas, utilisez-le quand même car il rend la requête plus rapide .

NOT IN

Seulement bon sans NULL valeurs ou si vous savez gérer NULL correctement. Je ne le ferais pas l'utiliser à cette fin. De plus, les performances peuvent se détériorer avec des tables plus grandes.

SELECT ip 
FROM   login_log
WHERE  ip NOT IN (
   SELECT DISTINCT ip  -- DISTINCT is optional
   FROM   ip_location
   );

NOT IN porte un "trap" pour NULL valeurs de chaque côté :

  • Rechercher les enregistrements où la jointure n'existe pas

Question similaire sur dba.SE destinée à MySQL :

  • Sélectionner les lignes où la valeur de la deuxième colonne n'est pas présente dans la première colonne