Postgresql中的NOT EXISTS子句

时间:2012-06-28 05:41:10

标签: postgresql greenplum

任何人都知道如何在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)除了>> (2)不在。
具体来说,对于具有相同语法的查询,(3)LEFT JOIN大约需要5580ms,(4)EXCEPT大约需要13502ms,(2)NOT IN需要大于100000(实际上我没有等待使用它完成)。
NOT IN子句是否有任何特殊原因导致这么慢?

3 个答案:

答案 0 :(得分:27)

有三种(主要)方法可以进行此类查询:

  1. NOT EXISTS相关子查询

  2. NOT IN子查询

  3. LEFT JOIN IS NULL检查:

  4. 您发现第一种方式在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 ;
    

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

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

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

答案 1 :(得分:5)

您遗漏的部分错误可能会指向正确的方向。我认为它说“DETAIL:查询包含一个相关的子查询。”因此,您必须使用连接或非相关子查询重写这些。

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

至于第二个查询,请尝试

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

答案 2 :(得分:2)

SELECT * FROM tabA 
WHERE id not in  (SELECT id FROM tabB)