2012-04-06 15 views
7

acabo de correr a través de este interesting article here, mostrando cómo simular wm_concat() o group_concat() en Oracle mediante una consulta y ventanas jerárquicos funciones:cláusula de Oracle CONNECT BY después de la cláusula GROUP BY

SELECT deptno, 
     LTRIM(MAX(SYS_CONNECT_BY_PATH(ename,',')) 
     KEEP (DENSE_RANK LAST ORDER BY curr),',') AS employees 
FROM (SELECT deptno, 
       ename, 
       ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) AS curr, 
       ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) -1 AS prev 
     FROM emp) 
GROUP BY deptno 
CONNECT BY prev = PRIOR curr AND deptno = PRIOR deptno 
START WITH curr = 1; 

Aunque, creo que este no es un solución muy legible, es bastante interesante, específicamente porque la cláusula CONNECT BY .. STARTS WITH viene después de la cláusula GROUP BY. De acuerdo con the specification, esto no debería ser posible. ¡He intentado esto usando una consulta simple y funciona! Las siguientes dos consultas devuelven los mismos resultados:

-- wrong according to the specification: 
select level from dual group by level connect by level <= 2; 
-- correct according to the specification: 
select level from dual connect by level <= 2 group by level; 

¿Se trata de una función no documentada? ¿O solo indiferencia sintáctica por conveniencia? ¿O las dos declaraciones se comportan sutilmente de manera diferente?

Respuesta

2

Creo que esto es solo una diferencia de sintaxis insignificante.

Más específicamente, creo que se trata de un error de documentación. El diagrama de sintaxis para 8i implica que cualquier orden es compatible. Nada en el 8i reference implica que el orden haga la diferencia. Pero ese tipo de diagrama también implica que usted puede tener múltiples group_by_clause o hierarchical_query, lo cual no es cierto:

--You can't group twice: ORA-01787: only one clause allowed per query block 
select level from dual connect by level <= 2 group by level group by level; 

Mi conjetura es que cuando Oracle fija el diagrama de sintaxis para 9i También se olvidaron el orden podría ser diferente. O tal vez lo dejaron de lado intencionalmente, porque parece más lógico hacer primero la parte jerárquica.

Existen varias variaciones menores de sintaxis como esta que no están documentadas. No creo que eso signifique que no estén respaldados. Oracle probablemente se arrepiente de haber permitido tantas opciones extrañas y quiere que las cosas parezcan simples al menos. Por ejemplo, HAVING puede venir antes de GROUP BY, muchas de las antiguas funciones paralelas todavía funcionan (pero se ignoran), etc. (Por eso siempre me río cuando la gente dice que van a "analizar SQL" rápidamente - buena suerte averiguando esto !)

Oracle 8i sintaxis: Oracle 8i SELECT syntax

Oracle 9i sintaxis: Oracle 9i SELECT syntax

+0

Gracias por su investigación. Eso tiene sentido, por supuesto. Después de todo, en notación BNF, puede ser bastante difícil documentar la indiferencia de orden para dos cláusulas, como se puede ver en la documentación de [CONNECT BY ... START WITH/START WITH .. CONNECT BY] (http: // docs. oracle.com/cd/B28359_01/server.111/b28286/statements_10002.htm#i2126079), donde esto se vuelve ilegible. –

2

Mire los planes de ejecución. En mi entorno, son idénticos, con una operación CONNECT BY alimentando a un HASH GROUP BY. Por lo tanto, parece que colocar GROUP BY primero es solo una sintaxis impar que produce el mismo resultado que el orden más natural.

Técnicamente, esto es probablemente un error en el analizador, ya que como dices la especificación indica que la cláusula de consulta jerárquica debe venir antes de la cláusula group-by. Pero no parece hacer ninguna diferencia en cómo se ejecuta la consulta.

+1

bonito toque. También creo que esto es un error (o "función oculta") del analizador. Sin embargo, esta es una consulta trivial, el plan de ejecución (o incluso el resultado) aún puede diferir en uno más complejo ... –