2012-04-06 16 views
7

ho appena eseguito attraverso questo interesting article here, mostrando come simulare wm_concat() o group_concat() in Oracle utilizzando una query e finestre gerarchici funzioni:clausola di Oracle CONNECT BY dopo clausola 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; 

Anche se, ho trovato questo non è un soluzione molto leggibile, è abbastanza interessante, in particolare perché la clausola CONNECT BY .. STARTS WITH viene dopo la clausola GROUP BY. Secondo the specification, questo non dovrebbe essere possibile. Ho provato questo utilizzando una query semplice e funziona, però! Le due seguenti query restituiscono gli stessi risultati:

-- 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; 

È una funzionalità non documentata? O solo l'indifferenza della sintassi per comodità? O le due affermazioni si comportano in modo leggermente diverso?

risposta

2

Penso che questa sia solo una differenza di sintassi insignificante.

In particolare, penso che questo sia un bug di documentazione. Il diagramma di sintassi per 8i implica che entrambi gli ordini sono supportati. Nulla nel 8i reference implica l'ordine fa alcuna differenza. Ma questo schema anche tipo di implica che si può avere più o group_by_clausehierarchical_query, che non è vero:

--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; 

La mia ipotesi è che quando Oracle ha fissato il diagramma di sintassi per 9i hanno anche dimenticato l'ordine potrebbe essere diverso. O forse l'hanno intenzionalmente lasciato fuori, perché sembra più logico fare prima la parte gerarchica.

Ci sono diverse variazioni di sintassi minori come questa che non sono documentate. Non penso che significhi che non sono supportati. Probabilmente Oracle si pente di aver permesso così tante opzioni strane e vuole che le cose sembrino almeno semplici. Ad esempio, può arrivare prima dello GROUP BY, molte delle vecchie funzionalità parallele funzionano ancora (ma vengono ignorate), ecc. (Questo è il motivo per cui ridono sempre quando le persone dicono che stanno rapidamente "analizzando SQL" - buona fortuna a pensarci !)

Oracle 8i sintassi: Oracle 8i SELECT syntax

Oracle 9i sintassi: Oracle 9i SELECT syntax

+0

Grazie per la tua ricerca. Questo ha senso, ovviamente. Dopo tutto, nella notazione BNF, può essere piuttosto complicato documentare l'indifferenza degli ordini per due clausole, come si può vedere nella documentazione di [CONNECT BY ... START WITH/START WITH .. CONNECT BY] (http: // docs. oracle.com/cd/B28359_01/server.111/b28286/statements_10002.htm#i2126079), laddove ciò diventa illeggibile. –

2

Guarda i piani di esecuzione. Nel mio ambiente sono identici, con un'operazione CONNECT BY che si inserisce in un HASH GROUP BY. Quindi sembra che piazzare prima il GROUP BY sia solo una sintassi dispari che produce lo stesso risultato dell'ordinamento più naturale.

Tecnicamente, questo è probabilmente un bug nel parser, dal momento che, come dici tu, la specifica indica che la clausola di query gerarchica dovrebbe precedere la clausola group-by. Ma non sembra fare alcuna differenza nel modo in cui viene eseguita la query.

+1

buon suggerimento. Penso anche che questo sia un bug (o "feature nascosta") del parser. Tuttavia, questa è una query banale, il piano di esecuzione (o anche il risultato) potrebbe ancora differire in uno più complesso ... –

Problemi correlati