
WINDOW FUNCTIONの理解と活用方法 - 日本エクセム株式会社 Oracle 技術情報
目次[非表示]
- 1.基本情報
- 1.1.Window Function Syntax
- 1.2.テストに関連するScript
- 2.COUNT()
- 3.問題と解決
- 3.1.SQL[1]. パフォーマンスの問題が発生した SQL ビルドの種類
- 3.2.SQL[2]. パフォーマンスの問題が発生した SQL ビルドの種類
- 3.3.SQL[1]. SQLビルドタイプは、SQL[2] のパフォーマンスの問題を解決する
- 4.RANK(), ROW_NUMNER(), DENSE_RANK()
- 4.1.SQL[1]
- 4.2.SQL[1]. RANKを利用する
- 4.3.SQL[2]. ROW_NUMBERを使用する
- 4.4.SQL[3]. DENSE_RANKを利用する
- 4.5.Analytic Functionの使用
- 5.結論
基本情報
Window Functionは、行と行の関係を簡単に定義できるよう設計された関数である。Window Function を使用すると、複雑な SQLを1つの SQL文に変更でき、 アクセスを繰り返す非効率性の問題を簡単に解決できる。このホワイトペーパーでは、Window Functionのランク (RANK、ROW_NUMBER、DENSE_RANK) および集計 (COUNT) に関連するセクションについて説明する。
Window Function Syntax
Window FunctionはOver()関数が、基本的に含まれなければならない。Over()関数と一緒に Window Functionが一緒に使われる。
テストに関連するScript
COUNT()
1A |
15 |
1A |
10 |
1A |
10 |
1A |
5 |
1 |
1A |
10 |
2 |
1A |
15 |
1 |
<最終的な抽出データ>
1A |
5 |
1 |
4 |
1A |
10 |
2 |
4 |
1A |
10 |
2 |
4 |
1A |
15 |
1 |
4 |
上記の<抽出データ>の図は、c1 = 1 and c2 = ‘A’であるデータをすべて抽出しc1、c2カラムにグループ化された件数とc1、c2、c3にグループ化された件数を図にしたものである。単純に以下のSQL [ 1 ]のようにT4テーブルのデータを重複アクセス(COUNT実行するために)実行し、処理することもできる。もちろん、<抽出データ>のデータを示すことはできるがSQLの性能は低下します。
問題と解決
SQL[1]. パフォーマンスの問題が発生した SQL ビルドの種類
1A |
5 |
1 |
4 |
1A |
10 |
2 |
4 |
1A |
10 |
2 |
4 |
1A |
15 |
1 |
4 |
次のSQL[2]は、T4テーブルのデータへの重複アクセスを避けるために、Oracle 9i以降のバージョンでは、SELECT AS WITH CLAUSEを使用すると、T4テーブルのデータに繰り返しアクセスすることなく、1行で予期されるデータを抽出できます。
SQL[2]. パフォーマンスの問題が発生した SQL ビルドの種類
1A |
5 |
1 |
4 |
1A |
10 |
2 |
4 |
1A |
10 |
2 |
4 |
1A |
15 |
1 |
4 |
しかし、問題がある。WITH CLAUSEを用いてT4テーブルのデータを1回だけ読むには、C1 = 1 AND C2 = ‘A’の条件に該当するすべてのデータをGLOBAL TEMPORARY TABLEに保存しておき、再使用する必要があるということである。
ところが、もしC1 = 1 AND C2 =’A’の条件に該当するデータが多く、OLTP環境で頻繁に使用するSQLならGLOBAL TEMPORARY TABLEを作成して処理する作業自体が負担になることになる。また、対応するSQLがページング時に使用されるクエリ文であれば、部分範囲がされていない、また多くの他の問題が発生する可能性があります。
上記のSQLでT4テーブルのデータを不必要に重複アクセス処理することなく、SQLの性能まで考慮したSQLの書き方は下記のようにCOUNT(* )OVER ()を活用するものである。
SQL[1]. SQLビルドタイプは、SQL[2] のパフォーマンスの問題を解決する
1A |
10 |
2 |
4 |
1A |
10 |
2 |
4 |
1A |
15 |
1 |
4 |
RANK(), ROW_NUMNER(), DENSE_RANK()
1A |
5 |
1A |
10 |
1A |
10 |
1A |
15 |
2E |
3 |
2E |
4 |
3G |
1 |
3G <最終的な抽出データ> |
2 |
C1 C2 |
C3 |
上記のデータを抽出する場合、C2 の値は “A”、”E”、”G”、 <C3 は最大値を抽出してデータ > を抽出する必要がある。Oracle 10g より前に、次のパターンを使用してSQLを記述してデータを抽出し、同じテーブルを2回繰り返し処理した。
SQL[1]
1A |
15 |
2E |
4 |
3G |
2 |
Oracle 10gの後、上記の <抽出データ>抽出方法として新しいAnalytic Function関数で 開くと、SQLは1回だけ処理され、同じテーブルを繰り返し処理しないことが保証される。この時、使用されるFUNCTIONがRANK, DENSE_RANK, ROW_NUMBERである。
SQL[1]. RANKを利用する
1A |
15 |
2E |
4 |
3G |
2 |
SQL[2]. ROW_NUMBERを使用する
1A |
15 |
2E |
4 |
3G |
2 |
SQL[3]. DENSE_RANKを利用する
1A |
15 |
2E |
4 |
3G |
2 |
Analytic Functionの使用
SQL[1] 、SQL[2] 、SQL[3]は、<抽出データ>に合致するデータを抽出することができる。ここで使用されるAnalytic Functionは RANK, DENSE_RANK, ROW_NUMBERである。RANK, DENSE_RANK, ROW_NUMBER Analytic Functionは、データをランク付けする解析関数であるが、データの正確な目的を知る必要がある。
1A |
15 |
1 |
1 |
1 |
1A |
10 |
2 |
2 |
2 |
1A |
10 |
2 |
2 |
3 |
1A |
5 |
4 |
3 |
4 |
・RANK: 同じンク (RANK – 2) に同じ値が 2 つある場合、次の値のランクは RANK – 4 である。
・DENSE_RANK: 同じランク(RANK-2)に同じ値が2つある場合、次の値のランクは RANK -3になる。
・ROW_NUMBER: 同じランクも順位が付けられる。
結論
ここまで、Window Functionの活用方法について簡単に説明しました。これは単純な例ですが、Window Functionをうまく利用すれば、 実際の作業SQLを書くときに、より効率的な SQLを記述することができます。