215

我有两个 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

4 回答 4

498

这项任务基本上有 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;

请注意(根据文档):

除非使用,否则将消除重复项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 INNULL对两边的值都有一个“陷阱” :

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

于 2013-10-14T16:22:17.437 回答
4

A.) 该命令不存在,您缺少“S”。

B.) 改用 NOT IN

SELECT ip 
  FROM login_log 
  WHERE ip NOT IN (
    SELECT ip
    FROM ip_location
  )
;
于 2013-10-14T15:18:04.250 回答
2

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 表中的一些数据。我只检索 executions1 表中不存在的数据。(甚至我在里面给出了一些你也可以给出的条件。)指定在检索数据时不应该存在的条件应该在括号内。

于 2017-12-04T08:29:25.817 回答
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
于 2015-03-11T18:49:43.907 回答