Det finns i princip fyra tekniker för denna uppgift, alla standard SQL.
NOT EXISTS
Ofta snabbast i 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
);
Tänk också på:
- Vad är lättare att läsa i EXISTS-underfrågor?
LEFT JOIN / IS NULL
Ibland är detta snabbast. Ofta kortast. Resulterar ofta i samma frågeplan som 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
Kort. Inte lika lätt att integrera i mer komplexa frågor.
SELECT ip
FROM login_log
EXCEPT ALL -- "ALL" keeps duplicates and makes it faster
SELECT ip
FROM ip_location;
Observera att (per dokumentation):
dubbletter elimineras om inte
EXCEPT ALL
används.
Vanligtvis vill du ha ALL
nyckelord. Om du inte bryr dig, använd det fortfarande eftersom det gör frågan snabbare .
NOT IN
Bara bra utan NULL
värden eller om du vet att hantera NULL
ordentligt. Jag skulle inte använda den för detta ändamål. Dessutom kan prestandan försämras med större bord.
SELECT ip
FROM login_log
WHERE ip NOT IN (
SELECT DISTINCT ip -- DISTINCT is optional
FROM ip_location
);
NOT IN
har en "fälla" för NULL
värden på båda sidor:
- Hitta poster där anslutning inte finns
Liknande fråga på dba.SE riktad mot MySQL:
- Välj rader där värdet för den andra kolumnen inte finns i den första kolumnen