2012-07-31 21 views
16

Estoy tratando de aprender SQL, usando PostgreSQL 9.1.3. Me gustaría entender algún comportamiento que me parece inconsistente. A saber:PostgreSQL anidado CTE y UNION

Esto funciona:

WITH innermost AS (SELECT 2) 
SELECT * FROM innermost 
UNION SELECT 3; 

me sale esto:

?column? 
---------- 
     2 
     3 

Esto funciona:

WITH outmost AS (
     (WITH innermost AS (SELECT 2) 
     SELECT * FROM innermost) 
)         
SELECT * FROM outmost; 

Resultado:

?column? 
---------- 
     2 

Esto también funciona:

WITH outmost AS (
    SELECT 1 
    UNION (WITH innermost AS (SELECT 2) 
     SELECT * FROM innermost) 
) 
SELECT * FROM outmost; 

me sale esto:

?column? 
---------- 
     1 
     2 

Pero esto no trabajo:

WITH outmost AS (
    SELECT 1 
    UNION (WITH innermost as (SELECT 2) 
     SELECT * FROM innermost 
     UNION SELECT 3) 
) 
SELECT * FROM outmost; 

Resultado:

ERROR: relation "innermost" does not exist 
LINE 4:   SELECT * FROM innermost 

Según mi modo de pensar, el último debería tener éxito o uno de los otros debería fallar. No veo el patrón. ¿Hay alguna regla general que me permita predecir qué combinaciones de CTE anidados y UNION funcionarán o no?

+0

Aunque su consulta final se ve incómodo, debería estar bien, en mi humilde opinión. Podría ser un error de precedencia/asociatividad en el analizador. Hay algunas restricciones semánticas (sin CTE recursivos anidados, IIRC); tal vez el analizador es demasiado quisquilloso, o demasiado gatillo feliz. Personalmente, utilizo muchos CTE anidados (hasta 4 niveles de profundidad), pero rara vez uso UNION, excepto en los CTE recursivos. – wildplasser

+2

@AdamMackler debe poner eso como la respuesta a su propia pregunta – araqnid

+3

Tom Lane reconociendo que encontró un error, es algo así como una aprobación oficial que hizo una muy buena pregunta. Por favor, publique lo que obtuvo de la lista como respuesta y asegúrese de agregar un enlace al hilo. –

Respuesta

17

El misterio está resuelto: el comportamiento que estaba observando es un error conocido. Envié el mismo post original a una lista específica de PostgreSQL y obtuve esta respuesta:.

Esto es un error :-(El código de análisis de análisis parece pensar que con sólo puede ser conectado a la parte superior o nivel un SELECT de nivel de hoja dentro de un árbol de operaciones de conjunto , pero la gramática sigue el estándar SQL que dice que no existe. El WITH se acepta y se adjunta a la UNIÓN de nivel intermedio que es donde debe ir sintácticamente, y luego se ignorará por completo durante el análisis de análisis. Verá aproximadamente corrigiéndolo

 regards, tom lane 

http://archives.postgresql.org/pgsql-novice/2012-07/msg00113.php

+3

Parece que esto se ha corregido en 9.2 beta3. Cito el boletín informativo: '* Soluciona el problema WITH con las operaciones de configuración (UNION/INTERSECT/EXCEPT)'. –

+2

Acabo de instalar 9.2beta3 y sí, el comando que no funciona en mi publicación original funciona ahora como se esperaba. Gracias por el aviso. –

+0

¡Genial! Gracias por rastrear esto! Tu pregunta merece más votos favorables. :) Por cierto, se recomienda aceptar su propia respuesta (correcta) en tal caso. –