我有两个postgresql表:
table name column names
----------- ------------------------
login_log ip | etc.
ip_location ip | location | hostname | etc.
我想从login_log
获取ip_location
中没有行的每个IP地址。
我尝试了这个查询,但它会引发语法错误。
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`
我也想知道这个查询(进行调整以使其工作)是否是用于此目的的最佳性能查询。
答案 0 :(得分:301)
这项任务基本上有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;
请注意(per documentation):
除非使用
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
带有“{1}}值的”陷阱“:
针对MySQL的dba.SE上的类似问题:
答案 1 :(得分:3)
A。)命令不是EXISTS,你错过了'S'。
B。)改为使用NOT IN
SELECT ip
FROM login_log
WHERE ip NOT IN (
SELECT ip
FROM ip_location
)
;
答案 2 :(得分:0)
这也可以尝试......
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
答案 3 :(得分:0)
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表包含所有数据和执行1表包含testcases1表中的一些数据。我只检索exections1表中不存在的数据。 (甚至我给出了一些你也可以给出的条件。)指定条件,不应该在那里检索数据应该在括号内。