Выберите строки, которых нет в другой таблице
у меня есть две таблицы postgresql:
table name column names
----------- ------------------------
login_log ip | etc.
ip_location ip | location | hostname | etc.
Я хочу получить каждый IP-адрес от login_log который не имеет строки в ip_location.
Я пробовал этот запрос, но он выдает синтаксическую ошибку.
SELECT login_log.ip
FROM login_log
WHERE NOT EXIST (SELECT ip_location.ip
FROM ip_location
WHERE login_log.ip = ip_location.ip)
ERROR: syntax error at or near "SELECT"
LINE 3: WHERE NOT EXIST (SELECT ip_location.ip`
мне также интересно, является ли этот запрос (с настройками, чтобы он работал) наиболее эффективным запросом для этой цели.
4 ответов:
есть в основном 4 метода для этой задачи, все они стандартные SQL.
NOT EXISTSчасто, Это самый быстрый в Postgres.
SELECT ip FROM login_log l WHERE NOT EXISTS ( SELECT -- mostly irrelevant what's here; might just be empty in pg FROM ip_location i WHERE l.ip = i.ip );также считают:
LEFT JOIN / IS NULLиногда это быстрее всего. Часто кратчайший.
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, to keep duplicate rows and make it faster SELECT ip FROM ip_location;обратите внимание, что (в документации):
дубликаты исключаются, если это.
как правило, вы хотите
ALLключевое слово. Если вам все равно, все равно используйте его, потому что он делает запрос быстрее.
NOT INтолько хорошо без нулевых значений или если вы знаете, чтобы обрабатывать 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:
A.) Команда не существует, вы пропускаете 'S'.
B.) используйте не вместо
SELECT ip FROM login_log WHERE ip NOT IN ( SELECT ip FROM ip_location ) ;
SELECT * FROM testcases1 t WHERE NOT EXISTS ( SELECT 1
FROM executions1 i WHERE t.tc_id = i.tc_id and t.pro_id=i.pro_id and pro_id=7 and version_id=5 ) and pro_id=7 ;здесь testcases1 таблица содержит все данные и executions1 таблица содержит некоторые данные среди testcases1 таблицы. Я получаю только данные, которые не присутствуют в таблице exections1. ( и даже я даю некоторые условия внутри, которые вы также можете дать.) укажите условие, которое не должно быть там в получении данных должно быть в скобках.
это также можно попробовать...
SELECT l.ip, tbl2.ip as ip2, tbl2.hostname FROM login_log l LEFT JOIN (SELECT ip_location.ip, ip_location.hostname FROM ip_location WHERE ip_location.ip is null)tbl2
Comments