2012-04-06 19 views
7

Właśnie natknąć tym interesting article here, pokazując w jaki sposób symulować wm_concat() lub group_concat() w Oracle przy użyciu hierarchicznego zapytania i okiennych funkcje:Oracle CONNECT BY klauzula po klauzuli 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; 

chociaż uważam, że to nie jest bardzo czytelne rozwiązanie, jest całkiem interesujące, szczególnie dlatego, że klauzula CONNECT BY .. STARTS WITH pochodzi od po z klauzuli GROUP BY. Według the specification nie powinno to być możliwe. Próbowałem tego za pomocą prostego zapytania i to działa! Następujące dwa zapytania zwracają takie same wyniki:

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

Czy to jest nieudokumentowana funkcja? Lub po prostu obojętność składni dla wygody? Czy też te dwa stwierdzenia subtelnie zachowują się inaczej?

Odpowiedz

2

Myślę, że jest to po prostu niewielka różnica w składni.

Dokładniej, myślę, że to błąd w dokumentacji. Schemat składniowy dla 8i oznacza, że ​​jest obsługiwana dowolna kolejność. Nic w numerze 8i reference nie oznacza, że ​​kolejność ma znaczenie. Ale to także rodzaj diagramu wynika, że ​​można mieć wiele group_by_clause lub hierarchical_query, co nie jest prawdą:

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

Domyślam się, że gdy Oracle stała diagram składni dla 9i one również zapomniał kolejność może być inna. A może celowo go opuścili, ponieważ wydaje się bardziej logiczne, aby najpierw wykonać część hierarchiczną.

Istnieje kilka mniejszych odmian składni, takich jak ten, które są nieudokumentowane. Nie sądzę, że oznacza to, że nie są obsługiwane. Oracle prawdopodobnie żałuje, że zezwala na tak wiele dziwnych opcji i chce, żeby rzeczy przynajmniej wyglądały na proste. Na przykład HAVING może nadejść przed GROUP BY, wiele starych funkcji równoległych nadal działa (ale są one ignorowane) itp. (Dlatego zawsze śmieję się, gdy ludzie mówią, że szybko "analizują SQL" - powodzenia w ustalaniu tego !)

Oracle 8i składnia: Oracle 8i SELECT syntax

Oracle 9i składnia: Oracle 9i SELECT syntax

+0

Dzięki za twoje badania. To oczywiście ma sens. W końcu, w notacji BNF, może być dość trudnym dokumentowanie obojętności kolejności dla dwóch klauzul, co można zobaczyć w dokumentacji [CONNECT BY .. START WITH/START WITH .. CONNECT BY] (http: // docs. oracle.com/cd/B28359_01/server.111/b28286/statements_10002.htm#i2126079), gdzie staje się to zupełnie nieczytelne. –

2

Spójrz na plany wykonania. W moim środowisku są identyczne, z operacją CONNECT BY zasilającą HASH GROUP BY. Wygląda więc na to, że umieszczenie najpierw GROUP BY jest po prostu dziwną składnią, która daje taki sam wynik, jak bardziej naturalne uporządkowanie.

Jest to prawdopodobnie błąd w analizatorze składni, ponieważ według ciebie specyfikacja wskazuje, że klauzula zapytania hierarchicznego powinna pochodzić wcześniej niż klauzula group-by. Ale wydaje się, że nie ma żadnej różnicy w sposobie wykonywania kwerendy.

+1

Nicea wskazówkę. Uważam też, że jest to błąd (lub "ukryta funkcja") analizatora składni. Jednak jest to banalne zapytanie, plan wykonania (lub nawet wynik) może jeszcze różnić się w bardziej złożonym ... –