Ответ 1
Есть в основном 4 метода для этой задачи, все они стандартные SQL.
NOT EXISTS
Часто самый быстрый в 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
);
Также учтите:
LEFT JOIN/IS NULL
Иногда это быстрее всего. Часто самый короткий. Часто приводит к тому же плану запроса, что и 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
Короткий. Не так легко интегрировать в более сложные запросы.
SELECT ip
FROM login_log
EXCEPT ALL -- "ALL" keeps duplicates and makes it faster
SELECT ip
FROM ip_location;
Обратите внимание, что (согласно документации):
дубликаты удаляются, если не используется
EXCEPT ALL
.
Как правило, вам нужно ключевое слово ALL
. Если вам все равно, все равно используйте его, потому что это делает запрос быстрее.
NOT IN
Хорошо только без значений NULL
или если вы знаете, как правильно обрабатывать NULL
. Я бы не использовал это для этой цели. Производительность может ухудшиться с большими таблицами.
SELECT ip
FROM login_log
WHERE ip NOT IN (
SELECT DISTINCT ip -- DISTINCT is optional
FROM ip_location
);
NOT IN
несет "ловушку" для значений NULL
с обеих сторон:
Аналогичный вопрос на dba.SE, ориентированный на MySQL: