ウィンドウ関数¶
ウィンドウ関数は、クエリ結果の行全体で計算を実行します。HAVING
句の後、ORDER BY
句の前に実行されます。ウィンドウ関数を呼び出すには、次のようにOVER
句を使用してウィンドウを指定する特別な構文が必要です。
function(args) OVER (
[PARTITION BY expression]
[ORDER BY expression [ASC|DESC]]
[frame]
)
フレームは次のいずれかです。
{RANGE|ROWS|GROUPS} frame_start {RANGE|ROWS|GROUPS} BETWEEN frame_start AND frame_end
frame_start
とframe_end
は次のいずれかになります。
UNBOUNDED PRECEDING
expression PRECEDING
CURRENT ROW
expression FOLLOWING
UNBOUNDED FOLLOWING
ウィンドウ定義には3つの構成要素があります。
PARTITION BY
句は、入力行を異なるパーティションに分割します。これは、集計関数に対してGROUP BY
句が行を異なるグループに分割する方法に似ています。PARTITION BY
が指定されていない場合、入力全体が単一のパーティションとして扱われます。ORDER BY
句は、ウィンドウ関数によって入力行が処理される順序を決定します。ORDER BY
が指定されていない場合、順序は定義されていません。**ウィンドウ関数内のORDER BY句は、序数をサポートしていません。実際の式を使用する必要があります。**frame
句は、特定の入力行に対して関数によって処理される行のスライディングウィンドウを指定します。フレームはROWS
型、RANGE
型、またはGROUPS
型にすることができ、frame_start
からframe_end
まで実行されます。frame_end
が指定されていない場合、デフォルト値のCURRENT ROW
が使用されます。ROWS
モードでは、CURRENT ROW
は現在の行を具体的に指します。RANGE
とGROUPS
モードでは、CURRENT ROW
はORDER BY
の目的で現在の行のピア行を指します。ORDER BY
が指定されていない場合、すべての行は現在の行のピア行と見なされます。RANGE
とGROUPS
モードでは、CURRENT ROW
のフレーム開始は現在の行の最初のピア行を指し、CURRENT ROW
のフレーム終了は現在の行の最後のピア行を指します。ROWS
モードでは、expression PRECEDING
またはexpression FOLLOWING
のフレームの開始と終了は、現在の行の前または後の指定された行数の開始または終了を定義します。expression
はINTEGER
型である必要があります。RANGE
モードでは、expression PRECEDING
またはexpression FOLLOWING
のフレームの開始と終了は、現在の行からのソートキーの値の差を定義します。ソートキーはexpression
と同じ型であるか、expression
と同じ型に変換できる必要があります。GROUPS
モードでは、expression PRECEDING
またはexpression FOLLOWING
のフレームの開始と終了は、現在の行からのグループ数を定義します。グループには、ソートキーで同じ値を持つすべての行が含まれます。expression
の型はINTEGERまたはBIGINTである必要があります。フレームが指定されていない場合、
RANGE UNBOUNDED PRECEDING
のデフォルトフレームが使用されます。
例¶
次のクエリは、担当者ごとに価格で注文をランク付けします。
SELECT orderkey, clerk, totalprice,
rank() OVER (PARTITION BY clerk
ORDER BY totalprice DESC) AS rnk
FROM orders
ORDER BY clerk, rnk
次のクエリは、フレーム定義におけるROWS
、RANGE
、およびGROUPS
の違いを示しています。
SELECT
ARRAY_AGG(v) OVER (
ORDER BY k ASC ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
)
FROM (
VALUES (1, 'a'), (1, 'b'), (3, 'c'), (3, 'd'), (5, 'e')
) t(k, v); -- ['a', 'b'], ['a', 'b', 'c'], ['b', 'c', 'd'], ['c', 'd', 'e'], ['d', 'e']
SELECT
ARRAY_AGG(v) OVER (
ORDER BY k ASC RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
)
FROM (
VALUES (1, 'a'), (1, 'b'), (3, 'c'), (3, 'd'), (5, 'e')
) t(k, v); -- ['a', 'b'], ['a', 'b'], ['c', 'd'], ['c', 'd'], ['e']
SELECT
ARRAY_AGG(v) OVER (
ORDER BY k ASC GROUPS BETWEEN 1 PRECEDING AND 1 FOLLOWING
)
FROM (
VALUES (1, 'a'), (1, 'b'), (3, 'c'), (3, 'd'), (5, 'e')
) t(k, v); -- ['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e'], ['c', 'd', 'e']
集計関数¶
すべての集計関数は、OVER
句を追加することでウィンドウ関数として使用できます。集計関数は、現在の行のウィンドウフレーム内の行に対して、各行ごとに計算されます。
たとえば、次のクエリは、担当者ごとに日ごとの注文価格の累積合計を生成します。
SELECT clerk, orderdate, orderkey, totalprice,
sum(totalprice) OVER (PARTITION BY clerk
ORDER BY orderdate) AS rolling_sum
FROM orders
ORDER BY clerk, orderdate, orderkey
ランキング関数¶
- cume_dist() -> double()¶
値のグループにおける累積分布を返します。結果は、ウィンドウパーティションのウィンドウ順序付けにおいて、行の前にある行または行と等しい行の数、をウィンドウパーティション内の行の総数で割ったものです。したがって、順序付けにおける任意の同値な値は、同じ分布値になります。
- dense_rank() -> bigint()¶
値のグループにおける順位を返します。これは
rank()
に似ていますが、同値な値によってシーケンスにギャップが生じることはありません。
- ntile(n) -> bigint()¶
各ウィンドウパーティションの行を
n
個のバケットに分割します。バケットの範囲は1
から最大n
です。バケット値の差は最大で1
です。パーティション内の行数がバケット数で割り切れない場合、残りの値は最初のバケットから始めて、バケットごとに1つずつ分配されます。例えば、
6
行と4
個のバケットの場合、バケット値は次のようになります。1
1
2
2
3
4
- percent_rank() -> double()¶
値のグループにおけるパーセンタイル順位を返します。結果は
(r - 1) / (n - 1)
であり、ここでr
は行のrank()
であり、n
はウィンドウパーティション内の行の総数です。
- rank() -> bigint()¶
値のグループにおける順位を返します。順位は、行の前にあり、その行と等しくない行の数に1を加えたものです。したがって、順序付けにおける同値な値は、シーケンスにギャップを生じさせます。ランキングは、各ウィンドウパーティションに対して実行されます。
- row_number() -> bigint()¶
ウィンドウパーティション内の行の順序に従って、1から始まる各行の一意のシーケンシャル番号を返します。
値関数¶
値関数は、関数を評価する際にNULL値をどのように処理するかを指定するオプションを提供します。NULLは無視することも(IGNORE NULLS
)、尊重することも(RESPECT NULLS
)できます。デフォルトでは、NULL値は尊重されます。IGNORE NULLS
が指定されている場合、値式がNULLであるすべての行は計算から除外されます。IGNORE NULLS
が指定され、すべての行で値式がNULLの場合、default_value
が返されます。指定されていない場合はnull
が返されます。
- first_value(x) -> [same as input]()¶
ウィンドウの最初の値を返します。
- last_value(x) -> [same as input]()¶
ウィンドウの最後の値を返します。
- nth_value(x, offset) -> [same as input]()¶
ウィンドウの先頭からの指定されたオフセット位置の値を返します。オフセットは
1
から始まります。オフセットは任意のスカラー式にすることができます。オフセットがNULLの場合、またはウィンドウ内の値の数より大きい場合、NULLが返されます。オフセットがゼロまたは負であることはエラーです。
- lead(x[, offset [, default_value]]) -> [same as input]()¶
ウィンドウパーティション内の現在の行の
offset
行後の値を返します。オフセットは0
から始まり、これは現在の行です。オフセットは任意のスカラー式にすることができます。デフォルトのoffset
は1
です。オフセットがnull
の場合、null
が返されます。オフセットがパーティション内にある行を参照しない場合、default_value
が返されます。指定されていない場合はnull
が返されます。
- lag(x[, offset [, default_value]]) -> [same as input]()¶
ウィンドウパーティション内の現在の行の
offset
行前の値を返します。オフセットは0
から始まり、これは現在の行です。オフセットは任意のスカラー式にすることができます。デフォルトのoffset
は1
です。オフセットがnull
の場合、null
が返されます。オフセットがパーティション内にある行を参照しない場合、default_value
が返されます。指定されていない場合はnull
が返されます。