Comments
Description
Transcript
Oracle8iR8.1.6 の分析関数
Oracle8iR8.1.6 の分析関数 Oracle テクニカル・ホワイト・ペーパー 1999 年 10 月 はじめに SQL 言語は多くの分野できわめて有能ですが、分析タスクに対するサポートは強力でありません。移動平均、ラ ンク付け、リード/ラグ比較などの基本的なビジネス・インテリジェンス計算は、標準 SQL 範囲外のパフォーマン ス上の課題をしばしば伴う幅広いプログラミングを必要とします。Oracle8i R8.1.6 は、こうした長年のニーズに 対応するパワフルな新しい SQL 関数群を提供しています。これらの関数は、あらゆるタイプの分析に有益なため、 "分析関数"と総称されています。分析関数は、パフォーマンスの向上と、開発作業の効率化をもたらします。さら に、これらの新しい関数は、2000 年の SQL 標準に追加されるものとして、現在 ANSI により検討されています。 4 つの分析関数群 Oracle は、それぞれ複数の関数で構成する 4 つの分析関数群を構築しました。 • ランク付け関数群 − "各地域の売上で上位 10 人および下位 10 人の営業担当者は?" 、または"各地域で、 売上の 25%を占める営業担当者は?"というようなビジネス上の質問に応答します。各関数は、出力結果全 体をチェックしてから答えを返します。Oracle は、RANK、DENSE_RANK、PERCENT_RANK、CUME_DIST、 および NTILE というランク付け関数を提供しています。 • ウィンドウ集約関数群 − "13 週間における株価の移動平均は?"、または"各地域の売上累積合計は?"のよう な質問に対応します。この新機能は、AVG、SUM、MIN、MAX、COUNT、VARIANCE、および STDDEV を含むすべての SQL 集約関数について、移動および累積処理を提供します。 • レポート集約関数群 − 最も一般的なタイプの計算の 1 つは、非集約値を集約値と比較することです。合 計に対する値の比率やマーケット・シェアの計算はすべて、この処理を必要とします。レポート集約関数 群は、このような計算を単純にします。異なる集約レベルで計算された値を、同一の行に配置できるので す。結合操作を必要としないため、集約値を詳細行と比較できるようになります。この新しい関数群は、 AVG、SUM、MIN、MAX、COUNT、VARIANCE、および STDDEV を含むすべての SQL 関数に ついて、 レポート集約処理を提供します。 • ラグ/リード関数群 − 変動や差異の考察は、分析の中心的な作業です。当然ながら、これには、表内の 異なる行の値を比較する操作が関わります。これは、一般にセルフ結合を使用して SQL でも可能ですが、 効率的でなく、計算式の作成も簡単ではありません。ラグ/リード関数群は、現在の行からのオフセットを 指定するだけで、表内の異なる行を比較できるようにします。 分析関数は、意思決定支援処理用リレーショナル・データベース・プラットフォームのパワーを補足することを 目的としており、特殊な OLAP 環境の役割に代わるものではないことに注意してください。Oracle OLAP Server の ような OLAP 製品を使用すれば、分析関数の能力を活用して問合せパフォーマンスを強化することができます。 利点 分析関数は、データベースのパフォーマンスと開発者の効率の両方を高めます。対話型意思決定支援からバッチ・ レポート・ジョブまで、あらゆるタイプの処理に有益です。社内の開発者と、独立したソフトウェア・ベンダー の両方が、この機能の利点を活用できます。新しい関数が提供する主な利点を紹介しましょう。 • 問合せ速度の向上 − これらの関数がサポートする処理の最適化機能により、問合せのパフォーマンスが 飛躍的に向上します。これまではセルフ結合または複雑な手続き処理を必要としていた操作が、本来の SQL Oracle8i のための分析関数 1999 年 10 月 2 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 で実行できるようになりました。新しい関数が実現するパフォーマンスの強化は、Oracle の MOLAP シス テムおよび他の ROLAP 製品に対する問合せ速度を向上させます。 • 開発作業の効率化 − 新しい関数は、開発者が、より明解で簡潔な SQL コードを使用して複雑な分析を実 行できるようにします。以前は、複数の SQL 文または手続き言語の使用を必要としていたタスクが、1 つ の SQL 文で表現できるようになりました。新しい SQL は、以前のアプローチよりも計算式の作成およびメ ンテナンスが容易なため、生産性が大幅に向上します。 • 最小限の学習作業 − 構文が入念に設計された分析関数は、新しいキーワードを習得する必要を最小限に します。この構文は、SUM や AVERAGE などの既存の集約関数を活用し、使い慣れたこれらのキーワード を広範囲の用途に使用できます。 • 標準化された構文 − ANSI SQL 標準の一部である新しい関数は、独立したソフトウェア・ベンダーにとっ て魅力的です。新しい関数を活用するように自社製品を修正する作業を促進します。Oracle は、問合せ製 品、レポート関連製品、および OLAP 製品の各ベンダーと協力し、分析関数の活用を支援しています。こ れまで、複数のデータベース・ベンダーがこれらの関数と同じ分野で独自の拡張機能を提供してきました。 しかし、そのような拡張機能は、大きなマーケット・シェアを獲得するには至らず、自社の関数に修正を 加えたソフトウェア・ベンダーもわずかにすぎませんでした。これに対し、新しい分析関数は、多数の独 立したソフトウェア・ベンダーによってサポートされています。「参考」の 1. ANSI 提案書をご参照くださ い。 コンセプト 分析関数は、その動作を実行するために、いくつかの新しい要素を SQL 処理に追加しています。これらの要素は 既存の SQL を基本としており、柔軟でパワフルな計算式が可能になります。以下に、分析関数に使用されている 重要なコンセプトを紹介します。 • 処理順序 − 分析関数を使用する問合せ処理は、3 つの段階で実行されます。第 1 段階では、すべての結合 と、WHERE 句、GROUP BY 句、および HAVING 句が実行されます。第 2 段階では、結果セットが分析関 数に適用され、すべての関数計算が実行されます。第 3 段階では、問合せの最後に ORDER BY 句があれば ORDER BY が実行され、出力データが正しい順序でソートされます。図 1 に、この処理順序を示します。 結合、 WHERE 句、 GROUP BY 句、 および HAVING 句 パーティションの作成、 各パーティションの 各行に分析関数を適用 最終的な ORDER BY 図 1:分析関数の処理順序 • 結果セットのパーティション − 分析関数では、パーティションと呼ばれる、順序が指定された行グルー プに問合せ結果セットを分割することができます。分析関数で使用される"パーティション"という用語は、 Oracle の表パーティション機能とは無関係ですので注意してください。本書では、"パーティション"を分析 関数に関連した意味でのみ使用しています。パーティションは、GROUP BY 句で定義されたグループの後 Oracle8i のための分析関数 1999 年 10 月 3 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 に作成されるため、SUM や AVG などの集約結果をパーティションに適用できます。パーティションへの 分割は、任意の列または式に基づいて行うことができます。問合せ結果セットは、すべての行を収容する 1 つだけのパーティションで構成しても、少数の大きなパーティションや、それぞれ数行ずつの多数の小さ なパーティションに分割してもかまいません。 • ウィンドウ − 各パーティションについて、データのスライド式ウィンドウが定義されます。このウィン ドウは、"現在行"(次の黒丸付き項で定義)に対する計算の実行に使用される行の範囲を決定します。ウィ ンドウのサイズは、物理的な行数か、時間などの論理的な間隔に基づいて設定することができます。ウィ ンドウには、開始行と終了行があります。ウィンドウには、その定義に応じて、一端だけが移動するもの と、両端が移動するものがあります。たとえば、累積合計関数に定義されるウィンドウは、開始行がパー ティションの先頭行に固定され、終了行は、開始ポイントからパーティションの最終行までスライドしま す。これに対し、移動平均に定義されるウィンドウは、物理的または論理的範囲が一定になるように、開 始ポイントと終了ポイントの両方がスライドします。 ウィンドウのサイズは、最大でパーティション内のすべての行まで拡大できます。最小サイズは、パーティ ション内の 2 行だけで構成するスライド式セットになります。ユーザーは、一定数の行が含まれるウィン ドウ、または指定した範囲の列値を持つすべての行が含まれるウィンドウを指定できます。また、日付の 値が前月に該当するすべての行を収容するウィンドウを定義することもできます。 • 現在行 − 分析関数で実行される各計算は、ウィンドウ内の現在行に基づいて実行されます。現在行は、 ウィンドウの開始および終了を決定するリファレンス・ポイント(基準点)として機能します。たとえば、 中心移動平均計算には、現在行、その前の 5 行、およびその後の 6 行を収容ウィンドウを定義できます。 これにより、図 2 に示す 12 行のスライド式ウィンドウが作成されます。 パーティションの開始 ウィンドウの開始 現在行:ウィンドウのコンテンツに基づく計算 ウィンドウの終了 ウィンドウの 移動方向 パーティションの終了 図 2:12 行の中心移動平均用のスライド式ウィンドウによるパーティション Oracle8i のための分析関数 1999 年 10 月 4 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 特長および用例 この節では、新しい関数の主な特長を説明し、基本的な用例を示します。本書は、各関数の内容および概念の記 述を目的としており、構文図は記載いたしません。ただし、新しい関数の価値を示すために、多数の実用的なケー スは紹介します。用例のほとんどは、各行に詳細または集約売上データが収容されている sales 表からのデータが 関わっています。 ランク付け関数群 ランク付け関数群の関数は、メジャー・セットの値に基づいて、データセット内の他の行と対比させた各行のラ ンクを計算します。分析処理の多くのニーズに対応するため、ランク付け関数群は、複数の異なる関数を提供し ています。これらの関数すべてに、次の機能を使用することができます。 • 複数の式に基づいてデータをランク付けする機能。たとえば、売上、利益、および年功序列の組合せに基 づいてランク付けすることができます。その場合、データは、売上、利益、および年功序列を基準として 順序が決定され、その後でランクが割り当てられます。複数の式に基づくランク付け能力により、タイ(等 値)のランクを最小化します。 • 関数に使用する式ごとに、昇順または降順のランク付け順序を指定できます。 • 順序の方向(昇順か降順)を問わず、NULL を強制して、最後または最初にランク付けすることができま す。 • ランク関数は、各パーティションの境界でリセットされます。 • ランクは、GROUP BY CUBE 句および ROLLUP 句によって生成されたグループ境界でリセットできます。 以下の節では、ランク付け関数群の各関数に関する要点を記載します。次に紹介する RANK 関数は、他の関数よ りも詳細に説明されています。RANK について記述されたコンセプトは他の関数にも適用しますので、これ以降 は繰り返しません。 RANK 関数 RANK 関数は、各行のランクをランク 1 から順にソートして表示します。ユーザーは、オプションの PARTITION 句と、必須の ORDER BY 句を指定します。PARTITION キーワードは、ランク付けをリセットする位置を定義する ために使用されます。ランク付けされる特定の列は、ORDER BY 句によって決定されます。パーティションを指 定しないと、結果セット全体に対してランク付けが実行されます。RANK は、降順が指定されていない限り、最 小値にランク 1 を割り当てます。次の例は、各地域の営業担当者を売上金額に基づいてランク付けします。 SELECT sales_person, sales_region, sales_amount, RANK() OVER (PARTITION BY s_region ORDER BY s_amount DESC) FROM Sales_table; Oracle8i のための分析関数 1999 年 10 月 5 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 sales_person sales_region sales_amount rank Adams Baker Connors Davis Edwards Fitzhugh Gariabaldi East East East East West West West 100 99 89 75 74 66 45 1 2 3 4 1 2 3 上表の"rank"列には、sales_amount の降順に営業担当者が表示され、sales_region が変化した時点でランクの値がリ セットされています。 集約関数を使用したランク付け この例では、問合せに GROUP BY 句が含まれており、各製品の売上合計に基づいてランク付けが行われます。 SELECT r_regionkey, p_productkey, sum(s_amount), RANK() OVER (PARTITION BY r_regionkey ORDER BY sum(s_amount) DESC) AS rank_of_product_per_region FROM product, region, sales WHERE r_regionkey = s_regionkey AND p_productkey = s_productkey GROUP BY r_regionkey, p_productkey; 1 つの問合せ内に異なる境界を持つランク付け 1 つの問合せブロックに、それぞれ異なるグループに対して動作する(異なる境界でリセットする)複数のランク 付け関数を含めることができます。次の問合せは、各地域の売上金額に基づく製品のランク付け (rank_of_product_per_region)と、全地域の売上金額に基づく製品のランク付け(rank_of_product_total)を行いま す。 SELECT r_regionkey, p_productkey, sum(s_amount), RANK() OVER (PARTITION BY r_regionkey ORDER BY sum(s_amount) DESC) AS rank_of_product_per_region, RANK() OVER (ORDER BY sum(s_amount) DESC) AS rank_of_product_total FROM product, region, sales WHERE r_regionkey = s_regionkey AND p_productkey = s_productkey GROUP BY r_regionkey, p_productkey ORDER BY r_regionkey; Oracle8i のための分析関数 1999 年 10 月 6 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 r_region key p_product key s_amount rank_of_product _per_region rank_of_ product_total east east east east east east east west west west west west west west shoes jackets shirts sweaters t-shirts ties pants shoes jackets t-shirts sweaters shirts ties pants 130 95 80 75 60 50 20 100 99 89 75 75 66 45 1 2 3 4 5 6 7 1 2 3 4 4 6 7 1 4 6 7 11 12 14 2 3 5 7 7 10 13 一番右の 2 つの列は、2 つの異なるランクを計算することに注意してください。rank_of_product_total は、すべての 行を対象としたランク付けですが、rank_of_product_per_region は、地域が west に変化した時点でリセットされて います。また、タイ値がランク付けでどのように処理されているかも注意してください。タイ値の処理について は、DENSE_RANK 関数の項で詳しく説明します。 キューブおよびロールアップ・グループ別のランク付け RANK は、Oracle8i に導入された CUBE または ROLLUP 演算子が行うグループ化に基づいてリセットできます。 CUBE/ROLLUP を使用すると、GROUPING(x)関数がグループ化の境界を検知し、x が、グループ化された列の一 部である場合は"0"を返し、x が小計である場合は"1"を返します。GROUPING()フラグは、リセットをトリガーす るために PARTITION BY 句内で使用できます。たとえば、次の問合せは、それぞれのグループ内の製品および地 域をランク付けします。キー値が NULL と等しい行は小計です。出力表を見やすくするため、グループの変り目 で行を太線で区切ってあります。 SELECT r_regionkey, p_productkey, sum(s_amount), RANK() OVER (PARTITION BY GROUPING(r_regionkey), GROUPING(p_productkey) ORDER BY sum(s_amount) DESC) AS rank_per_cube FROM product, region, sales WHERE r_regionkey = s_regionkey AND p_productkey = s_productkey GROUP BY CUBE(r_regionkey, p_productkey) ORDER BY GROUPING(r_regionkey), GROUPING(p_productkey), r_regionkey; Oracle8i のための分析関数 1999 年 10 月 7 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 r_regionkey p_productkey s_amount rank_per_cube east east east east east east east shoes jackets shirts sweaters t-shirts ties pants 130 50 80 75 60 95 20 1 12 6 7 11 4 14 west west west west west west west shoes jackets shirts sweaters t-shirts ties pants 100 99 89 75 75 66 45 2 3 5 7 7 10 13 east west null null 510 549 2 1 null null null null null null null shoes jackets shirts sweaters t-shirts ties pants 230 149 169 150 135 161 65 1 5 2 4 6 3 7 null null 1059 1 上表の最後の 3 つのセグメントは、小計の値を示しています。製品の値が NULL と等しい 2 行は、地域ごとの全 製品を対象とした小計、地域の値が NULL と等しい 7 行は、製品ごとの全地域を対象とした小計、そして最後の セグメントは総合計です。 DENSE_RANK 関数 DENSE_RANK 関数は、タイ値の処理方法を除いて RANK 関数と同一です。ランク付けにタイ値が含まれている 場合、「タイ値の次の値には、どのランクを割り当てるべきか?」という大きな問題があります。ランクを 1 つだ け大きくすべきでしょうか? それとも、タイ値の数に対応するランクを飛び越すべきでしょうか? RANK 関数は、次の計算式を使用して、タイ値の後に続くランクの飛び越しを作成します。 Next rank after a tie, using RANK = tied rank + number of tied values Oracle8i のための分析関数 1999 年 10 月 8 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 たとえば、ランク 3 に対応する 2 行がタイである場合、次に割り当てられるランクは、4 ではなく 5 になります。 つまり、RANK 関数では、ランク付けリスト内でタイ値がある箇所が不連続になるのです。 これに対し、DENSE_RANK 関数は、どのランク値も飛び越さずにランクを割り当てます。タイ値が検知されると、 次の計算式を使用します。 Next rank after a tie, using DENSE_RANK = tied rank + 1 DENSE_RANK で計算されるランクには、不連続な箇所がありません。また、DENSE_RANK の最大値は、各パー ティション内の固有値のカウントと等しくなることにも注意してください。下表は、2 つの関数の出力の違いを対 比させたものです。 person amount RANK DENSE_RANK Adams 100 1 1 Baker 100 1 1 Connors 89 3 2 Davis 75 4 3 Edwards 75 4 3 Fitzhugh 66 6 4 Garibaldi 45 7 5 CUME_DIST(累積分布)関数 累積分布関数は、パーティション内の他の値に対する、特定の値の相対位置を計算します。CUME_DIST 関数は、 特定の行のパーティション内において、現在値の前にある行、または現在値とタイである行の割合として定義さ れます。ゼロから 1 まで(ゼロを除き 1 を含む)の小数付き数値を返します。CUME_DIST 関数の結果は、しばし ばパーセンタイル(百分位数)値と呼ばれます。デフォルト順序は昇順です。つまり、パーティション内の最小 値が、CUME_DIST の最も低い値を割り当てられます。 地域ごとの製品に対し、売上に基づいて CUME_DIST を割り当てるには、次の問合せを使用します。この例で、 "sales"データ表は、地域内の製品別に詳細な売上データを格納しています。希望の結果を算出するには、詳細レコー ドを合計する必要があります。 SELECT r_regionkey, p_productkey, SUM(s_amount) as s_amount, CUME_DIST() OVER (PARTITION BY r_regionkey ORDER BY SUM(s_amount)) AS cume_dist_per_region FROM region, product, sales WHERE r_regionkey = s_regionkey AND p_productkey = s_productkey GROUP BY r_regionkey, p_productkey ORDER BY r_regionkey, s_amount DESC; Oracle8i のための分析関数 1999 年 10 月 9 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 r_regionkey p_productkey s_amount cume_dist_per_region east shoes 130 1.00 east jackets 95 0.86 east shirts 80 0.71 east sweaters 75 0.57 east t-shirts 60 0.43 east ties 50 0.29 east pants 20 0.14 west shoes 100 1.00 west jackets 99 0.86 west t-shirts 89 0.71 west sweaters 75 0.43 west shirts 75 0.43 west ties 66 0.29 west pants 45 0.14 PERCENT_RANK 関数 PERCENT_RANK は CUME_DIST と良く似ていますが、行カウントではなくランク値を分子に使用します。従っ て、値グループに対する値のランクを返します。この関数は、一般に普及している多数のスプレッドシートで使 用できます。行の PERCENT_RANK は、次のように計算されます。 (パーティション内の行のランク−1)/(パーティション内の行数−1) PERCENT_RANK は、ゼロから 1 までの値を返します。ASCENDING(昇順)にソートされたセットの先頭行は、 PERCENT_RANK がゼロになります。 NTILE 関数 NTILE 関数を使用すると、3 分位、4 分位、10 分位、および他の一般的な要約統計値を簡単に計算できます。この 関数は、順序が指定されたパーティションを、"バケット"と呼ばれる指定された数のグループに分割し、パーティ ション内の各行にバケット値を割り当てます。NTILE を使用すると、データ・セットを 4 分割、3 分割などのグルー プに分割できるので非常に便利です。 バケット値は、各バケットに割り当てられる行が完全に同数になるか、他のバケットよりも 1 行だけ多くなるよ うに計算されます。たとえば、パーティション内に 100 行がある場合に、バケット数を 4 として NTILE 関数を実 行すると、25 行に 1、25 行に 2(...以下同様)のように値が割り当てられます。 パーティション内の行数が、所定数のバケットに等分できない(剰余なしで割り切れない)場合は、各バケット に割り当てられる行の数に最高 1 行の差異が生じます。余った行は、バケット番号が最も小さいものから順に、 各バケットに 1 行ずつ配分されます。たとえば、103 行のパーティションに NTILE(5)を使用すると、最初のバケッ トに 21 行、2 番目のバケットに次の 21 行、3 番目のバケットに次の 21 行、4 番目のバケットに次の 20 行、そし て 5 番目のバケットに最後の 20 行が割り当てられます。 Oracle8i のための分析関数 1999 年 10 月 10 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 副問合せを使用すると、列の境界ではなく、数値の範囲に基づいてリセットが行われる複雑なランク付けを作成 できます。これにより、バケット内でのデータのランク付けが可能になります。たとえば、次の問合せは、売上 金額に基づいて製品ごとの売上を 4 つのバケットに分割し、各 4 分割内で製品をランク付けします。 SELECT p_productkey, sum_s_amount, 4_tile, RANK() OVER (PARTITION BY 4_tile ORDER BY sum_s_amount DESC) AS rank_in_quartile FROM (SELECT p_productkey, sum(s_amount) as sum_s_amount, NTILE(4) (ORDER BY sum(s_amount) DESC) as 4_tile FROM product, sales WHERE p_productkey = s_productkey GROUP BY p_productkey); p_productkey sum_s_amount 4_tile rank_in_quartile shoes 100 1 1 jackets 90 1 2 shirts 89 2 1 sweaters 75 2 2 shirts 75 3 1 ties 66 3 2 pants 45 4 1 socks 45 4 1 注意: この例で副問合せを使用したのは、明解を期するためにすぎません。RANK 関数の PARTITION_BY 句内に、 "4_tile"を直接代入すれば、副問合せを使用せずに済みます。 ROW_NUMBER 関数 ROW_NUMBER 関数は、ORDER_BY 句で定義された順序で、固有の数字をパーティション内の各行に割り当てま す。これは、パーティション別に各行を採番する場合に便利です。ROW_NUMBER 関数は、ROWNUM 疑似列と は無関係ですので注意してください。行番号は、必ず 1 から始まります。以下に例を示します。 SELECT p_productkey, s_amount, ROW_NUMBER() (ORDER BY s_amount DESC NULLS LAST) AS srnum FROM product, sales WHERE p_productkey = s_productkey Oracle8i のための分析関数 1999 年 10 月 11 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 p_productkey s_amount srnum shoes jackets shirts t-shirts sweaters jeans ties pants belts socks suits 100 90 89 84 75 75 75 69 56 45 NULL 1 2 3 4 5 6 7 8 9 10 11 ウィンドウ集約関数群 ウィンドウ集約関数は順序が指定された行セットに対して動作し、各行について、その行を基準としたウィンド ウに対する集約値を返します。"現在までの銀行預金の累積合計を計算する"ような無限のウィンドウと、"91 日間 における株価の移動平均を計算する"ような有限のウィンドウを指定できます。ランク付け関数と同様に、まず データを各グループ(銀行口座など)にパーティション化し、各グループ内でウィンドウ機能関数を適用します。 たとえば、"各口座について、銀行預金の累積合計を日付順に表示する"関数を適用します。 ここでは、ウィンドウ集約関数を"関数群"と呼んでいますが、これに定義された新しいキーワードは数個だけです。 このファミリを、既存の集約関数(SUM、AVG、MIN、MAX、STDDEV、VARIANCE、および COUNT)に対応 する新しい構文および動作としてとらえるのも有益です。 ウィンドウ集約には、次の機能が使用できます。 • すべての既存集約関数(SUM、AVG、MIN、MAX、STDDEV、VARIANCE、および COUNT)を、ウィン ドウ集約として使用できます。同様に、分析関数とともに導入された新しい回帰分析関数もサポートされ ています。これには、次の関数が含まれます。VAR_SAMP, VAR_POP, STDDEV_SAMP, STDDEV_POP, COVAR_SAMP, COVAR_POP, REGR_SLOPE, EGR_INTERCEPT, REGR_R2, REGR_AVGX, REGR_AVGY, REGR_COUNT, REGR_SXX, REGR_SXY AND REGR_SYY. • 各ウィンドウ集約関数には、ウィンドウのサイズを定義するオプションの句を指定できます。この句を指 定しないと、無限のウィンドウになります。つまり、表またはパーティションの始まりで開始し、表また はパーティションの終わりで終了します。 • 各ウィンドウ関数には、ランク付け関数群で使用できるような、固有の順序指定句を使用できます。 • ウィンドウ集約関数は、各パーティションの境界でリセットされます。 • 各ウィンドウ集約関数は、複数の式に基づいてデータの順序を指定できます。複数の式に基づくランク付 け能力はタイ値を少なくし、繰返し結果が可能になります。 • 関数内で使用する式ごとに、昇順または降順を指定できます。 • 順序の方向(昇順か降順)を問わず、NULL の強制して、最後または最初にランク付けすることができま す。 Oracle8i のための分析関数 1999 年 10 月 12 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 ウィンドウ・サイズの定義 ウィンドウは、ユーザーのニーズに応じてさまざまな方法で定義できます。 • 物理的 ― 行数に基づいて、物理的なウィンドウ・サイズを指定できます。たとえば、"現在行の直前の 10 行を対象とした移動平均を返してください"のように表現できます。ウィンドウのサイズを指定する数値式 に加え、いくつかのキーワードを使用することができます。 CURRENT ROW--ウィンドウが、現在行で開始または終了することを指定します。 UNBOUNDED PRECEDING--ウィンドウが、パーティションの先頭行で開始することを指定します。 UNBOUNDED FOLLOWING--ウィンドウが、パーティションの最終行で終了することを指定します。 • 時間隔 ― 時間隔に基づいて、論理的なウィンドウ・サイズを指定できます。たとえば、"現在行の日付の 直前の 91 日間を対象とした株価の移動平均を返してください"のように表現できます。あるいは、"現在行 の時刻の直前の 100 秒間を対象とした温度の移動平均を返してください"という例です。この場合、順序指 定式は、時間隔が適用できるように日付式に対して評価されます。 • 値の範囲 ― 現在の値と、順序が指定されたシーケンス内の前の値との差異に基づいて、論理的なウィン ドウ・サイズを指定できます。差異が特定のサイズよりも小さい行は、ウィンドウに含まれます。たとえ ば、"現在行の人より身長が低く、身長差が 3 インチ以下のすべての人の平均身長を返してください"とい う問合せでは、"Height BETWEEN current.Height AND current.Height-3"に該当するすべての行がウィンドウ に含まれます。 次の例は、預金日に基づいて順序が指定された口座ごとに、累積残高を表示します。 SELECT Acct_number, Trans_date, Trans_amount, SUM(Trans_amount) OVER (PARTITION BY Acct_number ORDER BY Trans_date ROWS UNBOUNDED PRECEDING) AS Balance FROM Ledger ORDER BY Acct_number, Trans_date; Acct_number 73829 73829 73829 82930 82930 82930 Trans_date 1998-11-01 1998-11-05 1998-11-13 1998-11-01 1998-11-21 1998-11-29 Trans_amount 113.45 -52.01 36.25 10.56 32.55 -5.02 Balance 113.45 61.44 97.69 10.56 43.11 38.09 移動集約関数の例 次に示すのは、取引ごとに、その前の 30 日間にわたる移動平均取引金額を表示する時間ベースのウィンドウの例 です。 SELECT Trans_date, Trans_amount, AVG (Trans_amount) OVER (ORDER BY Trans_date) RANGE INTERVAL '30' DAY PRECEDING) FROM Ledger; Oracle8i のための分析関数 1999 年 10 月 13 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 中心集約関数の例 現在行を中心としたウィンドウ機能集約関数の計算、たとえば中心平均は、比較的単純です。次の例は、現在行 を中心として、現在行の前の 2 行および現在行の後の 2 行を含む、中心移動平均を計算します。 SELECT st_timekey, AVG(s_amount) OVER (ORDER BY st_timekey ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING) AS cavg FROM stock WHERE st_name = ‘orcl’; FIRST_VALUE 関数と LAST_VALUE 関数 FIRST_VALUE 関数および LAST_VALUE 関数は、ユーザーがウィンドウ集約関数の能力および柔軟性をフルに活 用できるように支援します。問合せが、先頭行および最終行をウィンドウから選択できるようにします。これら の行は、計算のベースラインとして使用されることが多いため特に重要です。たとえば、日付に基づいて順序が 指定された売上データを格納しているパーティションに対し、"各日の売上を、その期間の最初の営業日 (FIRST_VALUE)と比較する"ことができます。または、売上の昇順に順序が指定されている行セットに対し、" 地域内で最高の売上(LAST_VALUE)に対する各売上の比率"を知ることができます。 レポート集約関数群 1 つのレベルの集約を異なるレベルの集約と比較することは、分析作業の重要な部分です。たとえば、従業員の給 与を部門別平均給与と比較したり、その従業員を除く平均給与を知りたい場合があります。また、部門別平均給 与を全部門の平均給与と比較したい場合もあります。レポート集約ファミリでは、セルフ結合を使用せずに、異 なるレベルで集約した値を行に含めることができます。グループごとに 1 行ずつ(グループごとの合計など)を 返す SQL 集約関数とは異なり、レポート集約関数はウィンドウ・レベルで動作します。つまり、ウィンドウ内の すべての行について、同一の集約値を返します。 レポート集約関数は、ウィンドウ全体の集約、または現在行を除くウィンドウ全体の集約を計算します。ほとん どの点で、ウィンドウ集約関数と似ており、同様の機能を持っています。 レポート集約関数の例 "各製品について、売上が最高であった地域は?"という質問を考えてみましょう。レポート集約関数を使用すると、 インライン・ビューを使用して答えを見つけることができます。 Oracle8i のための分析関数 1999 年 10 月 14 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 SELECT s_productkey, s_regionkey, sum_s_amount FROM (SELECT s_productkey, s_regionkey, SUM(s_amount) as sum_s_amount, MAX(SUM(s_amount)) OVER (PARTITION BY s_productkey) as max_sum_s_amount FROM sales GROUP BY s_productkey, s_regionkey) WHERE sum_s_amount = max_sum_s_amount; インライン・ビューは、次の情報を返します。 s_productkey s_regionkey sum_s_amount max_sum_s_amount jackets west 99 99 jackets east 50 99 pants east 20 45 pants west 45 45 shirts east 60 80 shirts west 80 80 shoes west 100 130 shoes east 130 130 sweaters west 75 75 sweaters east 75 75 ties east 95 95 ties west 66 95 外部問合せは、必要な情報を返します。 s_productkey s_regionkey sum_s_amount jackets west 99 pants west 45 shirts west 80 sweaters west 75 sweaters east 75 shoes east 130 ties east 95 レポート集約関数を使用しないと、この問合せは、各製品について地域ごとに最高の売上を計算し、その値を sales 表と結合します。新しい関数を使用すると、結合を処理するコストが節減されます。 Oracle8i のための分析関数 1999 年 10 月 15 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 RATIO_TO_REPORT 関数 RATIO_TO_REPORT 関数関数は、ウィンドウ内の値セットの合計に対する値の比率を計算します。競合製品のマー ケット・シェアや、財務分析での原価配分のような占有率を計算するために使用できます。この関数は、一般的 な計算を能率化する省略形として活用できます。比率計算で、分母として使用する値を含む列を返す必要がなく なります。 次の例では、各製品の売上比率を RATIO_TO_REPORT で計算します。つまり、総売上に対する割合として、各製 品の占有率を計算します。レポート全体の売上合計を選択する必要がないことに注意してください。 SELECT s_productkey, SUM(s_amount) AS sum_s_amount, RATIO_TO_REPORT(SUM(s_amount)) OVER () AS ratio_to_report FROM sales GROUP BY s_productkey; s_productkey sum_s_amount ratio_to_report shoes 100 0.19 jackets 90 0.17 shirts 80 0.15 sweaters 75 0.14 shirts 75 0.14 ties 10 0.01 pants 45 0.08 socks 45 0.08 ラグ/リード関数群 分析作業の主要なタスクは、データ・セット内の値を比較することです。前年に対する月間売上の変動や、予算 と原価実績との差異が分析の対象になります。分析計算で、表内の 2 行を比較する必要がある場合、SQL ユーザー はセルフ結合を使用するのが一般的でした。LAG/LEAD 関数では、現在の行からのオフセットを指定するだけで、 別の行をアクセスできます。セルフ結合が必要でないため、パフォーマンスを大幅に向上させることができます。 LAG/LEAD 関数では、オフセットが表から逸脱した場合のデフォルト値も指定できます。次の例は、LAG/LEAD 関数を示したものです。 SELECT t_timekey, s_amount, LAG(s_amount,1) OVER (ORDER BY t_timekey) as LAG_amount, LEAD(s_amount,1) OVER (ORDER BY t_timekey) as LEAD_amount FROM sales, time WHERE sales.s_timekey = time.t_timekey ORDER BY t_timekey; Oracle8i のための分析関数 1999 年 10 月 16 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 t_timekey s_amount LAG_amount LEAD_amount 92-10-11 1 NULL 2 92-10-12 2 1 3 92-10-13 3 2 4 92-10-14 4 3 5 92-10-15 5 4 NULL 追加問合せ この節では、分析関数によって複雑な質問に対応する 2 つの例を紹介します。最初の問合せでは、電話会社の通 話詳細記録に関するものです。2 番目の問合せは、各都市を対象とした累積売上分析が関わります。 異なる期間における電話会社の顧客活動の例 この例は、当初、「参考」の「2.」に提示されたものです。この問合せは、FromAC、FromTel、ToAC、To Tel、 Date、および Length という列を持つ CALLS という 1 つの通話詳細記録表を使用します。この表は、すべての通話 について、発信元と着信先の両方の地域コードおよび電話番号を、通話日および通話時間とともに格納します。 ここに格納されたデータは、1998 年のものです。 次の問合せは、顧客ごとに、前半の 6 カ月間で、その年に発生したすべての通話の平均時間を超える通話の数と、 後半の 6 カ月間でこれと同じ平均時間を超える通話の数を返します。 SELECT FromAC, FromTel, COUNT( CASE WHEN (date >= TODATE('01-JAN-1998') and date <= TODATE('30-JUN-1998') and Length > ravg_Length) THEN 1 ELSE NULL ) as count_1, COUNT( CASE WHEN (date >= TODATE('01-JUL-1998') and date <= TODATE('31-DEC-1998') and Length > ravg_Length) THEN 1 ELSE NULL ) as count_2 FROM (SELECT FromAC, FromTel, Length, AVG(Length) OVER (PARTITION BY FromAC, FromTel) as ravg_Length FROM CALLS ) GROUP BY FromAC, FromTel; この問合せは、発信元の電話番号(FromAC、FromTel)ごとに、GROUP_BY を実行します。結果を計算するため に、2 つのパスを処理します。最初のパスでは、各パーティションの平均時間(ravg_Length)が(副問合せ内で) 計算され、2 番目のパスでは、グループごとに、平均時間を超える通話の合計数(count_1 および count_2)が計算 されます。 Oracle8i のための分析関数 1999 年 10 月 17 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 分析関数を使用しない場合は、まず、通話の平均時間を一時表またはインライン・ビューから計算し、それをファ クト表に結合しなおして、平均時間を超える通話の数をカウントしなければなりません。分析関数はより効率的 な処理を可能にします。 都市別の売上分析の例 これは、レポート集約関数を使用して売上データを分析する例です。各州について、売上が最高の都市を知りた い場合はどうすればよいでしょう。次の問合せは、"各州について、累積売上が州全体の売上の 50%を占める都市 だけを、売上の昇順に表示してください"というビジネス上の質問に答えます。 SELECT r_state, r_city, city_sales, cum_ratio FROM (SELECT r_state, r_city, SUM(s_amount) as city_sales, (SUM(SUM(s_amount)) OVER (PARTITION BY r_state ORDER BY SUM(s_amount) DESC ROWS UNBOUNDED PRECEDING)) / (SUM(SUM(s_amount)) OVER (PARTITION BY r_state)) as cum_pct FROM sales, region WHERE s_regionkey = r_regionkey GROUP BY r_state, r_city) WHERE cum_ratio <= 0.5; r_state r_city city_sales cum_pct California San Francisco 202,000 0.19 California Los Angeles 152,000 0.33 California San Jose 91,000 0.41 California San Diego 74,000 0.48 Colorado Denver 102,000 0.25 Colorado Colorado Springs 56,000 0.39 Colorado Boulder 39,000 0.49 この問合せは、州および都市(r_state、r_city)ごとに、GROUP BY を実行します。副問合せでは、各都市の総売 上(city_sales)を計算し、州の総売上に対する比率を、各行の累積合計(cum_pct)で表します。副問合せ内のレ ポート集約関数"(SUM(SUM(s_amount))OVER(PARTITION BY r_state)"は、比率計算の分母として使用される州の総 売上を与えることに注意してください。外部問合せは、結果をフィルタで選別し、比率の値が、各州の総売上の 半分未満を表す 0.5 より少ない行だけを表示します。 Oracle8i のための分析関数 1999 年 10 月 18 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 結論 分析関数は、Oracle サーバーによるパワフルで効率的な意思決定支援処理をサポートするという Oracle のコミッ トメントを示す重要な例です。Oracle 7.3 のビットマップ・インデックスから、Oracle 8.0 のスター結合問合せ変換、 そして Oracle8i のマテリアライズド・ビューまで、Oracle はスケーラブルな分析処理を一貫してリードしてきまし た。世界中のデータ・ウェアハウス、ビジネス・インテリジェンス・システム、および高度 OLAP 環境は、Oracle のコア・データベース・エンジンを基盤としています。 分析関数により Oracle は、問合せパフォーマンスの高速化および開発作業の効率化への新しい道を開きます。 Oracle は、最小限の新しい構文で、SQL での更なる表現力を可能にしました。Oracle は、新しい関数が、意思決 定支援処理のすべての範囲に多大な影響を与えると確信しています。分析関数のパワーは、ANSI 標準のステータ スと一体になり、すべての SQL ユーザーにとって価値あるツールを実現します。 Oracle8i のための分析関数 1999 年 10 月 19 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。 参考 1. Fred Zemke et al., Proposal for OLAP functions, ISO/IEC JTC1/SC32 WG3:YGJ-069r1 = ANSI NCITS H2-99-155r3. 2. D.Chatziantoniou and K.Ross, Querying Multiple Features of Groups in Relational Databases, Proceedings of VLDB Conference 1996, pages 295-306. Oracle Corporation World Headquarters 500 Oracle Parkway Redwood Shores, CA 94065 U.S.A. 世界共通窓口: +1.650.506.7000 FAX:+1.650.506.7200 http://www.oracle.com/ 版権 © Oracle Corporation 1999 無断転載を禁ず この文書はあくまでも参考資料であり、掲載されている情報は予告 なしに変更されることがあります。万一、誤植などにお気づきの場 合はオラクル社までお知らせください。オラクル社は本書の内容に 関していかなる保証もいたしません。また、本書の内容に関連した いかなる損害についても責任を負いかねます。 Oracle はオラクル社の登録商標です。Oracle8i、PL/SQL、Oracle8i Enterprise Edition、Oracle8i Standard Edition、および Oracle8 は、オ ラクル社の商標です。 他のすべての企業名と製品名は、識別のためにのみ掲載されており、 それぞれの所有者の商標です。 #J.Anal 2000/03/21 Oracle8i のための分析関数 1999 年 10 月 20 Oracle Corporation 発行の 「Analytic Functions for Oracle8i」 の翻訳版です。