OLAP 指定の使用
OLAP (Online Analytical Processing) 指定では、ランキング、行の番号付け、およびその他の集約関数情報を照会結果でスカラー値として戻す機能が提供されます。
例: ランキングおよび行の番号付け
SELECT EMPNO, SALARY,
RANK() OVER(ORDER BY SALARY DESC),
DENSE_RANK() OVER(ORDER BY SALARY DESC),
ROW_NUMBER() OVER(ORDER BY SALARY DESC)
FROM EMPLOYEE
FETCH FIRST 10 ROWS ONLY;この照会は次の情報を戻します。
| EMPNO | SALARY | RANK | DENSE_RANK | ROW_NUMBER |
|---|---|---|---|---|
| 000010 | 52,750.00 | 1 | 1 | 1 |
| 000110 | 46,500.00 | 2 | 2 | 2 |
| 200010 | 46,500.00 | 2 | 2 | 3 |
| 000020 | 41,250.00 | 4 | 3 | 4 |
| 000050 | 40,175.00 | 5 | 4 | 5 |
| 000030 | 38,250.00 | 6 | 5 | 6 |
| 000070 | 36,170.00 | 7 | 6 | 7 |
| 000060 | 32,250.00 | 8 | 7 | 8 |
| 000220 | 29,840.00 | 9 | 8 | 9 |
| 200220 | 29,840.00 | 9 | 8 | 10 |
この例では、上位 10 名の SALARY が降順で戻されます。 RANK 列は各給与の相対ランキングを示します。 2 行目に同じ給与を持つ 2 つの行があることに注意してください。 これらの各行には、同じランク値が割り当てられます。 以下の行には、値 4が割り当てられます。 RANK は、その行の前にある行の合計数より 1 つ多い行の値を戻します。 重複ができると常に、順序を示す番号に、抜けている数があることになります。
対照的に DENSE_RANK 列では、重複していた 2 位の行の次に 3 という値を表示します。 DENSE_RANK は、対象行の前にある別の内容の行の値に 1 を加えた数を戻します。 順序を示す番号は常に連続しています。
ROW_NUMBER は各行に対して固有の番号を戻します。 指定された順序に従って値が重複する行では、行番号の割り当ては任意になります。 照会が再度実行される際には、重複する行に対して異なる順序で行番号を割り当てることができます。
例: ランキング・グループ
SELECT WORKDEPT, INT(AVG(SALARY)) AS AVERAGE,
RANK() OVER(ORDER BY AVG(SALARY) DESC) AS AVG_SALARY,
NTILE(3) OVER(ORDER BY AVG(SALARY) DESC) AS QUANTILE
FROM EMPLOYEE
GROUP BY WORKDEPT; この照会は次の情報を戻します。
| WORKDEPT | AVERAGE (平均) | AVG_SALARY | QUANTILE |
|---|---|---|---|
| B01 | 41,250 | 1 | 1 |
| A00 | 40,850 | 2 | 1 |
| E01 | 40,175 | 3 | 1 |
| C01 | 29,722 | 4 | 2 |
| D21 | 25,668 | 5 | 2 |
| D11 | 25,147 | 6 | 2 |
| E21 | 24,086 | 7 | 3 |
| E11 | 21,020 | 8 | 3 |
この例では、NTILE 関数の引数が 3 になっていますが、 これは同じサイズの 3 つのセットに結果がグループ分けされることを意味します。 結果セットは変位値の数で均等に分割できないため、値が最も低い 2 つの変位値のそれぞれには 1 つずつ追加行が組み込まれます。
例: 部署内でのランキング
SELECT LASTNAME, WORKDEPT, BONUS,
DENSE_RANK() OVER(PARTITION BY WORKDEPT ORDER BY BONUS DESC)
AS BONUS_RANK_IN_DEPT
FROM EMPLOYEE
WHERE WORKDEPT LIKE 'E%';この照会は次の情報を戻します。
| LASTNAME | WORKDEPT | BONUS | BONUS_RANK_
IN_DEPT (BONUS_RANK_ IN_DEPT) |
|---|---|---|---|
| GEYER | E01 | 800.00 | 1 |
| HENDERSON | E11 | 600.00 | 1 |
| SCHNEIDER | E11 | 500.00 | 2 |
| SCHWARTZ | E11 | 500.00 | 2 |
| SMITH | E11 | 400.00 | 3 |
| PARKER | E11 | 300.00 | 4 |
| SETRIGHT | E11 | 300.00 | 4 |
| SPRINGER | E11 | 300.00 | 4 |
| SPENSER | E21 | 500.00 | 1 |
| LEE | E21 | 500.00 | 1 |
| GOUNOT | E21 | 500.00 | 1 |
| WONG | E21 | 500.00 | 1 |
| ALONZO | E21 | 500.00 | 1 |
| MENTA | E21 | 400.00 | 2 |
例: 表式の結果によるランキングおよび順序付け
給与が高い上位 5 名の従業員を部署名とともに検索しようとしているとします。 部署名は department 表に存在するため、結合操作が必要になります。 順序付けはネストされた表の式ですでに完了しているため、ROW_NUMBER 値の判別に順序付けを用いることも可能です。 これを実現するためには ORDER BY ORDER OF 表 文節が使用されます。
SELECT ROW_NUMBER() OVER(ORDER BY ORDER OF EMP),
EMPNO, SALARY, DEPTNO, DEPTNAME
FROM (SELECT EMPNO, WORKDEPT, SALARY
FROM EMPLOYEE
ORDER BY SALARY DESC
FETCH FIRST 5 ROWS ONLY) EMP,
DEPARTMENT
WHERE DEPTNO = WORKDEPT;この照会は次の情報を戻します。
| ROW_NUMBER | EMPNO | SALARY | DEPTNO | DEPTNAME |
|---|---|---|---|---|
| 1 | 000010 | 52,750.00 | A00 | SPIFFY コンピューター・サービス事業部 |
| 2 | 000110 | 46,500.00 | A00 | SPIFFY コンピューター・サービス事業部 |
| 3 | 200010 | 46,500.00 | A00 | SPIFFY コンピューター・サービス事業部 |
| 4 | 000020 | 41,250.00 | B01 | PLANNING |
| 5 | 000050 | 40,175.00 | E01 | サポート・サービス |
例: OLAP 集約および CUME_DIST の使用
部署 D11 の従業員の給与の移動合計と給与分布を知りたいとします。
SELECT ROW_NUMBER() OVER() AS ROW, LASTNAME, SALARY,
SUM(SALARY) OVER(ORDER BY SALARY
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS ROLLING_TOTAL_RANGE,
SUM(SALARY) OVER(ORDER BY SALARY
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS ROLLING_TOTAL_ROWS,
DECIMAL(CUME_DIST() OVER (ORDER BY SALARY),4,3) AS DISTRIBUTION
FROM EMPLOYEE
WHERE WORKDEPT = 'D11'
ORDER BY SALARY;この照会は次の情報を戻します。
| ROW | LASTNAME | SALARY | ロールイン _
TOTAL 範囲 |
ロールイン _
TOTAL_ ROWS |
DISTRIBUTION |
|---|---|---|---|---|---|
| 1 | JONES | 18,270.00 | 18,270.00 | 18,270.00 | .091 |
| 2 | WALKER | 20,450.00 | 38,720.00 | 38,720.00 | .182 |
| 3 | SCOUTTEN | 21,340.00 | 60,060.00 | 60,060.00 | .273 |
| 4 | PIANKA | 22,250.00 | 82,310.00 | 82,310.00 | .364 |
| 5 | YOSHIMURA | 24,680.00 | 131,670.00 | 106,990.00 | .545 |
| 6 | YAMAMOTO | 24,680.00 | 131,670.00 | 131,670.00 | .545 |
| 7 | ADAMSON | 25,280.00 | 156,950.00 | 156,950.00 | .636 |
| 8 | BROWN | 27,740.00 | 184,690.00 | 184,690.00 | .727 |
| 9 | LUTZ | 29,840.00 | 244,370.00 | 214,530.00 | .909 |
| 10 | JOHN | 29,840.00 | 244,370.00 | 244,370.00 | .909 |
| 11 | STERN | 32,250.00 | 276,620.00 | 276,620.00 | 1.000 |
この例では、グループの値を計算するときに使用されるウィンドウを定義する 2 つの方法が示されています。
最初の方法では RANGE を使用してウィンドウが定義されます。これは、ORDER BY の値が同じであるすべての行に対してグループを定義します。 行番号 5 と 6 は、給与の値が同じであるため、 1 つのグループとして扱われます。 これらの行の給与が合算され、前の合計に加算されて、 ROLLING_TOTAL_RANGE 列に示されているように、これらの行のそれぞれに対して同じ値が生成されます。
2 番目の方法では、 ROWS を使用してウィンドウが定義されます。これは、各行を 1 つのグループとして扱います。 ROLLING_TOTAL_ROWS 列では、現在行までの合計が各行に示されています。 行 5 と 6 のように給与値が同じ行の場合、返される順序は不定です。
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW は、デフォルトの集約グループであり、ROLLING_TOTAL_RANGE 指定から省略可能です。
ORDER BY が照会全体に指定されることで、行が順序付けられて返されることが保証されます。
例: RANGE ウィンドウ操作指定の使用
部署 D11 について給与をもっと詳細に分析したいとします。
次の例では、 各行の給与よりも 1000 少ないか多い給与値を処理する RANGE を使用して、ウィンドウ操作によって給与をまとめてグループ化します。 合計を計算するために使用される、グループの最初と最後の給与値も返します。
SELECT LASTNAME, SALARY,
SUM(SALARY) OVER(ORDER BY SALARY) AS ROLLING_TOTAL,
SUM(SALARY) OVER(ORDER BY SALARY
RANGE BETWEEN 1000 PRECEDING AND 1000 FOLLOWING) AS WINDOWED_TOTAL,
FIRST_VALUE(SALARY) OVER(ORDER BY SALARY
RANGE BETWEEN 1000 PRECEDING AND 1000 FOLLOWING),
LAST_VALUE(SALARY) OVER(ORDER BY SALARY
RANGE BETWEEN 1000 PRECEDING AND 1000 FOLLOWING)
FROM EMPLOYEE
WHERE WORKDEPT = 'D11'
ORDER BY SALARY;この照会は次の情報を戻します。
| LASTNAME | SALARY | ロールイン _
合計 |
WINDOWED_
合計 |
FIRST_VALUE | LAST_VALUE |
|---|---|---|---|---|---|
| JONES | 18,270.00 | 18,270.00 | 18,270.00 | 18,270.00 | 18,270.00 |
| WALKER | 20,450.00 | 38,720.00 | 41,790.00 | 20,450.00 | 21,340.00 |
| SCOUTTEN | 21,340.00 | 60,060.00 | 64,040.00 | 20,450.00 | 22,250.00 |
| PIANKA | 22,250.00 | 82,310.00 | 43,590.00 | 21,340.00 | 25,280.00 |
| YOSHIMURA | 24,680.00 | 131,670.00 | 74,640.00 | 24,680.00 | 25,280.00 |
| YAMAMOTO | 24,680.00 | 131,670.00 | 74,640.00 | 24,680.00 | 25,280.00 |
| ADAMSON | 25,280.00 | 156,950.00 | 74,640.00 | 24,680.00 | 25,280.00 |
| BROWN | 27,740.00 | 184,690.00 | 27,740.00 | 27,740.00 | 27,740.00 |
| LUTZ | 29,840.00 | 244,370.00 | 59,680.00 | 29,840.00 | 29,840.00 |
| JOHN | 29,840.00 | 244,370.00 | 59,680.00 | 29,840.00 | 29,840.00 |
| STERN | 32,250.00 | 276,620.00 | 32,250.00 | 32,250.00 | 32,250.00 |
従業員ごとに 1 つのグループが定義され、 そのグループには、その従業員の給与よりも 1000 少ない (PRECEDING)、または 1000 多い (FOLLOWING) 範囲内の給与である、部署 D11 のすべての他の従業員が含まれます。 WINDOWED_TOTAL 列には、 そのグループ内のすべての給与の合計が返されます。 FIRST_VALUE 列には、グループのうち最低の給与値が返されます。 LAST_VALUE 列には、グループのうち最高の給与値が返されます。 最も近い他の給与との差が 1000 を超える給与の従業員はその従業員自身で 1 つのグループになります。
ORDER BY が照会全体に指定されることで、行が順序付けられて返されることが保証されます。
例: ROWS ウィンドウ操作指定の使用
次の例では、各従業員給与の 1 行前と 1 行後にある給与値を処理する ROWS を使用して、ウィンドウ操作によって給与をまとめてグループ化します。 3 つの行の平均が返されます。
SELECT LASTNAME, SALARY,
DECIMAL(AVG(SALARY) OVER(ORDER BY SALARY
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)7,2) AS AVG_SALARY
FROM EMPLOYEE
WHERE WORKDEPT = 'D11'
ORDER BY SALARY;この照会は次の情報を戻します。
| LASTNAME | SALARY | AVG_SALARY |
|---|---|---|
| JONES | 18,270.00 | 19,360.00 |
| WALKER | 20,450.00 | 20,020.00 |
| SCOUTTEN | 21,340.00 | 21,346.66 |
| PIANKA | 22,250.00 | 22,756.66 |
| YOSHIMURA | 24,680.00 | 23,870.00 |
| YAMAMOTO | 24,680.00 | 24,880.00 |
| ADAMSON | 25,280.00 | 25,900.00 |
| BROWN | 27,740.00 | 27,620.00 |
| LUTZ | 29,840.00 | 29,140.00 |
| JOHN | 29,840.00 | 30,643.33 |
| STERN | 32,250.00 | 31,045.00 |