Postgresql中的NOT EXISTS子句

che*_*eng 20 postgresql greenplum

任何人都知道如何在Postgresql中执行此类查询?

SELECT * 
FROM tabA 
WHERE NOT EXISTS (
    SELECT * 
    FROM tabB 
    WHERE tabB.id = tabA.id
)
Run Code Online (Sandbox Code Playgroud)

当我执行这样的查询时,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
)
Run Code Online (Sandbox Code Playgroud)

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

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

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

ype*_*eᵀᴹ 27

有3种(主要)方法来执行此类查询:

  1. NOT EXISTS 相关子查询

  2. NOT IN 子查询

  3. LEFT JOINIS 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 ;
Run Code Online (Sandbox Code Playgroud)

这个(第四种方式)也适用于Postgres(支持EXCEPT运营商):

SELECT a.*
FROM a
WHERE id IN
      ( SELECT id
        FROM a
      EXCEPT
        SELECT id
        FROM b
      ) ; 
Run Code Online (Sandbox Code Playgroud)

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


Mar*_*ani 5

您遗漏的部分错误可能已将您指向正确的方向。我认为它说:“详细信息:该查询包含一个相关的子查询。” 因此,您必须使用联接或不相关的子查询来重写它们。

SELECT * FROM tabA WHERE id NOT IN (SELECT id FROM tabB);
Run Code Online (Sandbox Code Playgroud)

至于第二个查询,请尝试

SELECT * FROM tabA WHERE (id, id2) NOT IN (SELECT id, id2 FROM tabB);
Run Code Online (Sandbox Code Playgroud)