Istnieją zasadniczo 4 techniki do tego zadania, wszystkie z nich to standardowy SQL.
NOT EXISTS
Często najszybszy w Postgresie.
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
);
Weź również pod uwagę:
- Co jest łatwiejsze do odczytania w podzapytaniach EXISTS?
LEFT JOIN / IS NULL
Czasami jest to najszybsze. Często najkrótszy. Często skutkuje tym samym planem zapytania, co 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
Krótki. Nie tak łatwo integruje się z bardziej złożonymi zapytaniami.
SELECT ip
FROM login_log
EXCEPT ALL -- "ALL" keeps duplicates and makes it faster
SELECT ip
FROM ip_location;
Zwróć uwagę, że (zgodnie z dokumentacją):
duplikaty są eliminowane, chyba że EXCEPT ALL
jest używany.
Zazwyczaj potrzebujesz ALL
słowo kluczowe. Jeśli Ci to nie zależy, nadal go używaj, ponieważ sprawia, że zapytanie szybsze .
NOT IN
Tylko dobre bez NULL
wartości lub jeśli wiesz, jak obsłużyć NULL
odpowiednio. nie użyj go do tego celu. Również wydajność może się pogorszyć przy większych stołach.
SELECT ip
FROM login_log
WHERE ip NOT IN (
SELECT DISTINCT ip -- DISTINCT is optional
FROM ip_location
);
NOT IN
niesie „pułapkę” na NULL
wartości po obu stronach:
- Znajdź rekordy, w których połączenie nie istnieje
Podobne pytanie na dba.SE skierowane na MySQL:
- Wybierz wiersze, w których wartość drugiej kolumny nie występuje w pierwszej kolumnie