2012-04-06 17 views
7

BY GROUPの後に私はちょうど階層問合せとウィンドウ関数を使用してOracleでwm_concat()またはgroup_concat()をシミュレートする方法を示し、このinteresting article here全体を実行している:OracleのCONNECT 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; 

私はこれをない見つけ、が、非常に読みやすい解決策です。具体的には、CONNECT BY .. STARTS WITHという句がのGROUP BY節の後に来ると、が来るという理由で、かなり面白いです。 the specificationによると、これは可能ではありません。私は単純なクエリを使用してこれを試してみましたが、それは動作します!以下の2つのクエリは同じ結果を返します:

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

これは文書化されていませんか?便宜上、無関係な構文ですか?または、2つのステートメントは微妙に異なる動作をしますか?

答えて

2

これはほんのわずかな構文の違いだと思います。

もっと具体的には、これはドキュメントのバグだと思う。 8iの構文図は、どちらの順序もサポートされていることを示しています。 8i referenceに何も記載されていないと、注文に違いがあります。しかし、その図はまた、一種のあなたは真されていない、複数のgroup_by_clauseまたはhierarchical_queryを持つことができることを意味します

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

私の推測では、Oracleは9iのための構文図を固定するとき、彼らはまた、順序が異なる可能性が忘れてしまったということです。または、階層的な部分を最初に行う方が論理的であると思われるので、意図的にそれらを放棄した可能性があります。

このような文書化されていない軽微な構文がいくつかあります。私は彼らがサポートされていないことを意味するとは思わない。おそらくオラクルはあまりにも多くの奇妙なオプションを許しており、少なくともシンプルに見えるようにしたいと思っています。たとえば、HAVINGGROUP BYの前に来ることができますが、古い並列機能の多くはまだ動作しますが、無視されます(これは、人々がすぐに「SQLを解析する」と言ったときに私がいつも笑う理由です。 !)

のOracle 8iの構文: Oracle 8i SELECT syntax

のOracle 9iの構文: Oracle 9i SELECT syntax

+0

研究に感謝します。それはもちろん意味があります。結局のところ、BNF表記法では、[CONNECT BY .. WITH WITH START WITH CONNECT BY]の文書にあるように、2つの節の順序無関心を文書化するのは非常に難しいことがあります(http:// docs。 oracle.com/cd/B28359_01/server.111/b28286/statements_10002.htm#i2126079)、これはかなり読めなくなります。 –

2

実行計画を見てください。私の環境では、CONNECT BY操作がHASH GROUP BYに入力されています。したがって、GROUP BYを最初に配置すると、より自然な順序付けと同じ結果が得られる奇妙な構文になります。

これはおそらく、パーサーのバグです。スペックでは、階層問合せ句がgroup-by句の前に来る必要があると言っているからです。しかし、クエリの実行方法に違いはないようです。

+1

ニースのヒント。私はこれがパーサーのバグ(または "隠された特徴")だとも思っています。しかし、これは簡単なクエリです。実行計画(または結果)は、より複雑なものではまだ異なる場合があります。 –