9

階層クエリとウィンドウ関数を使用して、またはOracle でシミュレートする方法を示す、この興味深い記事をここで見つけました。wm_concat()group_concat()

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来るため、非常に興味深いものです。仕様によると、これは不可能です。簡単なクエリを使用してこれを試してみましたが、うまくいきます。次の 2 つのクエリは、同じ結果を返します。GROUP BY

-- 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 つのステートメントの動作が微妙に異なるのでしょうか?

4

2 に答える 2

4

これは些細な構文の違いだと思います。

より具体的には、これはドキュメントのバグだと思います。8i の構文図は、どちらの順序もサポートされていることを示しています。8i リファレンスには、順序によって違いが生じることを意味するものはありません。group_by_clauseしかし、その図は、複数のorを持つことができることを暗示していますが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 構文

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

于 2012-04-07T16:05:50.110 に答える
3

実行計画を見てください。私の環境では、それらは同一であり、CONNECT BY 操作が HASH GROUP BY にフィードされます。したがって、GROUP BY を最初に配置することは、より自然な順序付けと同じ結果を生成する単なる奇妙な構文のようです。

技術的には、これはおそらくパーサーのバグです。仕様では、階層クエリ句が group-by 句の前に来る必要があることを示しているためです。ただし、クエリの実行方法に違いはないようです。

于 2012-04-06T13:12:35.520 に答える