Esistono fondamentalmente 4 tecniche per questo compito, tutte SQL standard.
NOT EXISTS
Spesso il più veloce a 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
);
Considera anche:
- Cosa è più facile da leggere nelle sottoquery EXISTS?
LEFT JOIN / IS NULL
A volte questo è più veloce. Spesso il più corto. Spesso risulta nello stesso piano di query di 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
Breve. Non facilmente integrabile in query più complesse.
SELECT ip
FROM login_log
EXCEPT ALL -- "ALL" keeps duplicates and makes it faster
SELECT ip
FROM ip_location;
Nota che (per documentazione):
i duplicati vengono eliminati a meno che EXCEPT ALL
viene utilizzato.
In genere, vorrai il ALL
parola chiave. Se non ti interessa, usalo comunque perché rende la query più veloce .
NOT IN
Buono solo senza NULL
valori o se sai come gestire NULL
correttamente. Io non usalo per questo scopo. Inoltre, le prestazioni possono peggiorare con tabelle più grandi.
SELECT ip
FROM login_log
WHERE ip NOT IN (
SELECT DISTINCT ip -- DISTINCT is optional
FROM ip_location
);
NOT IN
porta una "trappola" per NULL
valori su entrambi i lati:
- Trova record in cui il join non esiste
Domanda simile su dba.SE mirata a MySQL:
- Seleziona le righe in cui il valore della seconda colonna non è presente nella prima colonna