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