select其他表中不存在的行

我有两个postgresql表:

table name column names ----------- ------------------------ login_log ip | etc. ip_location ip | location | hostname | etc. 

我想从login_log获取login_log中没有一行的每个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` 

我也想知道,如果这个查询(使其工作调整)是最好的查询为此目的。

这个任务基本上有4种技术,都是标准的SQL。

NOT EXISTS

通常情况下,这在Postgres中是最快的。

 SELECT ip FROM login_log l WHERE NOT EXISTS ( SELECT 1 -- it's mostly irrelevant what you put here FROM ip_location i WHERE l.ip = i.ip ); 

还要考虑:

  • 在EXISTS子查询中更容易阅读什么?

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; 

请注意( 每个文档 ):

除非使用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在两边都带有一个“陷阱”

  • 查找连接不存在的logging

针对MySQL的dba.SE上的类似问题:

  • select第一列中不存在第二列值的行

答:)命令不存在,你错过了'S'。

B.)用NOT IN代替

 SELECT ip FROM login_log WHERE ip NOT IN ( SELECT ip FROM ip_location ) ; 
 this can also be tried... 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