2012-06-28 25 views
14

¿Alguien sabe cómo realizar dicha consulta en Postgresql?cláusula NOT EXISTS en Postgresql

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

Cuando ejecuto dicha consulta, PostgreSQL se queja "ERROR: Greenplum Database does not yet support that query."

EDIT: ¿Y qué tal ésta:

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

EDIT:
Probé en PostgreSQL 8.2.15 para los 4 respuestas proporcionadas por @ypercube. Las conclusiones son:

1) El primero no funciona en esta versión de postgresql, como dije antes en la pregunta. El mensaje de error se puede encontrar allí también.

2) Para las otras tres respuestas, la velocidad de ejecución es: (3) UNIÓN IZQUIERDA> (4) EXCEPTO >> (2) NO EN.
Específicamente, para consultas que tienen la misma sintaxis, (3) LEFT JOIN toma aproximadamente 5580ms, (4) EXCEPTO toma aproximadamente 13502ms, y (2) NOT IN toma más de 100000 (De hecho, no esperé hasta que terminó).
¿Hay alguna razón particular para que la cláusula NOT IN sea tan lenta?
Cheng

+2

PostgreSQL 8.2 es antiguo y ya no es compatible. Hubo cambios importantes en cómo las consultas 'EXISTS' y' NOT EXISTS' funcionan desde entonces. http://www.postgresql.org/support/versioning/ – kgrittn

+0

Si desea encontrar las consultas más eficientes, creo que primero debe verificar los índices que tiene en las tablas.No mencionas el tamaño de las tablas, pero 5 segundos para una consulta significa (99%) tablas enormes o falta de índices. Le sugiero que agregue una nueva pregunta, incluidas las definiciones ('CREATE TABLE') de las dos tablas, las consultas y los planes de ejecución. –

Respuesta

21

Hay 3 (principales) maneras de hacer este tipo de consulta:

  1. NOT EXISTS consulta correlacionada

  2. NOT IN subconsulta

  3. LEFT JOIN con IS NULL cheque:

Se encontró que la primera forma funciona en Greenplum. @Marco y @juergen proporcionaron la 2da manera. Aquí está la tercera uno, se puede pasar por alto las limitaciones de Greenplum:

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

Este (cuarto ida) también trabaja en Postgres (que apoya EXCEPT operador):

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

Probado en SQL-Fiddle (que todo el 4 de trabajo en Postgres).

+0

@cheng: Por curiosidad, ¿funciona esto? –

+0

No, no es así. Creo que la razón es que el filtro "tabB.id IS NULL" se aplica antes de LEFT JOIN, no después de IZQUIERDA. – cheng

+0

¿Cómo implementar esta consulta con NOT EXISTS? ¿Puedes ofrecer alguna ayuda? – cheng

2
SELECT * FROM tabA 
WHERE id not in (SELECT id FROM tabB) 
+0

He actualizado mi pregunta, ¿cómo realizar la consulta actualizada en postgresql? – cheng

3

La parte del error que podría quedar fuera se han señalado en la dirección correcta. Creo que decía "DETALLE: la consulta contiene una subconsulta correlacionada". Por lo tanto, debe volver a escribirlos con combinaciones o subconsultas no correlacionadas.

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

En cuanto a la segunda consulta, trate

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

Gracias por responder tan pronto. Actualicé mi pregunta ¿Qué pasa con la nueva consulta? – cheng

+0

Sí, dice "La consulta contiene una subconsulta correlacionada". Este tipo de consulta es soportada directamente por mysql. Pensé que postgresql también lo soporta. – cheng

+0

postgres lo hace, con cosas mucho más complejas, pero greenplum no lo hace porque tiene que soltar la funcionalidad por razones de rendimiento. –