27

任何人都知道如何在 Postgresql 中执行这样的查询?

SELECT * 
FROM tabA 
WHERE NOT EXISTS (
    SELECT * 
    FROM tabB 
    WHERE tabB.id = tabA.id
)

当我执行这样的查询时,postgresql 抱怨“ ERROR: Greenplum Database does not yet support that query。”

编辑:这个怎么样:

SELECT * 
FROM tabA 
WHERE NOT EXISTS (
    SELECT * 
    FROM tabB WHERE tabB.id = tabA.id AND tabB.id2 = tabA.id2
)

编辑:
我在 postgresql 8.2.15 中测试了@ypercube 提供的 4 个答案。结论是:

1)第一个在这个版本的postgresql中不起作用,正如我在上面的问题中所说的那样。错误消息也可以在那里找到。

2)对于其他三个答案,执行速度为:(3)LEFT JOIN > (4)EXCEPT >> (2)NOT IN。
具体来说,对于具有相同语法的查询,(3)LEFT JOIN 大约需要 5580 毫秒,(4)EXCEPT 大约需要 13502 毫秒,以及(2)NOT IN 需要超过 100000(实际上我没有等待它完成)。
NOT IN 子句这么慢有什么特别的原因吗?

4

3 回答 3

32

有 3 种(主要)方法可以进行这种查询:

  1. NOT EXISTS相关子查询

  2. NOT IN子查询

  3. LEFT JOIN检查IS NULL

您发现第一种方法在 Greenplum 中确实有效。@Marco 和 @juergen 提供了第二种方式。这是第三个,它可能会绕过 Greenplum 的限制:

SELECT tabA.* 
FROM 
    tabA 
  LEFT JOIN 
    tabB 
      ON  tabB.id = tabA.id 
      AND tabB.id2 = tabA.id2
WHERE tabB.id IS NULL ;

这(第 4 种方式)也适用于 Postgres(支持EXCEPT运算符):

SELECT a.*
FROM a
WHERE id IN
      ( SELECT id
        FROM a
      EXCEPT
        SELECT id
        FROM b
      ) ; 

SQL-Fiddle中测试(所有 4 个都在 Postgres 中工作)。

于 2012-06-28T05:58:56.707 回答
5

您遗漏的部分错误可能会为您指明正确的方向。我认为它说“详细信息:查询包含相关子查询”。所以你必须用连接或不相关的子查询重写这些。

SELECT * FROM tabA WHERE id NOT IN (SELECT id FROM tabB);

至于第二个查询,试试

SELECT * FROM tabA WHERE (id, id2) NOT IN (SELECT id, id2 FROM tabB);
于 2012-06-28T05:44:03.780 回答
2
SELECT * FROM tabA 
WHERE id not in  (SELECT id FROM tabB)
于 2012-06-28T05:43:38.210 回答