我有两个postgresql表:
table name column names
----------- ------------------------
login_log ip | etc.
ip_location ip | location | hostname | etc.
我想从login_log
获取每个IP地址,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种技术,都是标准的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
对任何一方的NULL
值都有一个“陷阱”:
针对MySQL的dba.SE上的类似问题:
A.)命令不是EXISTS,你错过了'S'。
B.)使用NOT IN代替
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表包含所有数据和执行1表包含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