概要
ウィンドウ関数を初めて見た時にROWS と RANGE の違いが分かりませんでした。
サンプルデータを用いてROWSとRANGEのSQLをそれぞれ見ることで違いが分かったのでぜひ参考にしてください。
サンプルデータ
今回は、sample_date の値に重複があるケースを使います。
| sample_date | value |
|---|---|
| 2024-12-01 | 10 |
| 2024-12-01 | 15 |
| 2024-12-02 | 20 |
| 2024-12-02 | 25 |
| 2024-12-03 | 30 |
クエリ1: ROWS を使った集計
下記が使用したSQLです。
SELECT
sample_date,
value,
SUM(value)
OVER (
ORDER BY sample_date
ROWS BETWEEN 1 PRECEDING AND CURRENT ROW
) AS rows_sum
FROM LoadSample;
ROWS の計算過程
-
範囲指定:
ROWS BETWEEN 1 PRECEDING AND CURRENT ROWでは、現在の行とその1つ前の行のみが範囲に含まれます。PRECEDINGが前の行を指定する単語です。FOLLOWINGで後の行の指定ができます。 -
行単位で計算:
sample_dateが同じ値でも、行ごとに個別に計算されます。
| sample_date | value | 範囲 | rows_sum |
|---|---|---|---|
| 2024-12-01 | 10 | 現在の行(2024-12-01)のみ |
10 |
| 2024-12-01 | 15 |
2024-12-01 と 2024-12-01
|
10 + 15 = 25 |
| 2024-12-02 | 20 |
2024-12-01 と 2024-12-02
|
15 + 20 = 35 |
| 2024-12-02 | 25 |
2024-12-02 と 2024-12-02
|
20 + 25 = 45 |
| 2024-12-03 | 30 |
2024-12-02 と 2024-12-03
|
25 + 30 = 55 |
クエリ2: RANGE を使った集計
下記がSQL文です。
SELECT
sample_date,
value,
SUM(value)
OVER (
ORDER BY sample_date
RANGE BETWEEN 1 PRECEDING AND CURRENT ROW
) AS range_sum
FROM LoadSample;
RANGE の計算過程
-
範囲指定:
RANGE BETWEEN 1 PRECEDING AND CURRENT ROWでは、現在の行のsample_dateを基準にして、値の範囲が決まります。 -
sample_dateが同じ値の行がまとめて計算されるため、重複した値が範囲に含まれます。
| sample_date | value | 範囲 | range_sum |
|---|---|---|---|
| 2024-12-01 | 10 | 現在の行(2024-12-01)のみ |
10 |
| 2024-12-01 | 15 |
2024-12-01 と 2024-12-01
|
10 + 15 = 25 |
| 2024-12-02 | 20 |
2024-12-01 と 2024-12-02
|
10 + 15 + 20 = 45 |
| 2024-12-02 | 25 |
2024-12-01 と 2024-12-02
|
10 + 15 + 20 + 25 = 70 |
| 2024-12-03 | 30 |
2024-12-02 と 2024-12-03
|
20 + 25 + 30 = 75 |
ROWS と RANGE の違いのまとめ
| 特徴 | ROWS |
RANGE |
|---|---|---|
| 計算範囲 | 行単位で前後の行を基準に集計 |
sample_date の範囲に基づいて集計 |
| 重複行の扱い | 同じ sample_date があっても個別に計算 |
同じ sample_date はまとめて集計 |
| 集計結果 | 行単位で計算される | 値を基にした範囲で計算される |
このように、ROWS と RANGE の違いは、特に同じ値が重複している場合に顕著に現れます。ROWS は行単位で計算しますが、RANGE は同じ値を持つ行をまとめて集計します。