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