Open4
【達人に学ぶSQL徹底指南書メモ】2. 必ずわかるウィンドウ関数

2.1 ウィンドウ関数とは
2.1.1 無名ウィンドウ構文
ウィンドウの定義は暗黙に行われている。
SELECT
shohin_id,
shohin_mei,
hanbai_tanka,
AVG(hanbai_tanka) OVER(
ORDER BY
shohin_id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS moving_avg
FROM
Shohin
;
2.1.2 名前付きウィンドウ構文
ウィンドウの定義を明示するとこう ↓
OVER 句に入るのがウィンドウ 🪟
SELECT
shohin_id,
shohin_mei,
hanbai_tanka,
AVG(hanbai_tanka) OVER W AS moving_avg
FROM
Shohin
WINDOW W AS(
ORDER BY
shohin_id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
)
;
名前付きウィンドウ構文では、ウィンドウを使いまわせる。
SELECT
shohin_id,
shohin_mei,
hanbai_tanka,
AVG(hanbai_tanka) OVER W AS moving_avg,
SUM(hanbai_tanka) OVER W AS moving_sum,
COUNT(hanbai_tanka) OVER W AS moving_count,
MAX(hanbai_tanka) OVER W AS moving_max
FROM
Shohin
WINDOW W AS(
ORDER BY
shohin_id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
)
;

2.2 ORDER BY
LoadSample
sample_date | load_val |
---|---|
2018-02-01 | 1024 |
2018-02-02 | 2366 |
2018-02-05 | 2366 |
2018-02-07 | 985 |
2018-02-08 | 780 |
2018-02-12 | 1000 |
1 行前にずらす
SELECT
sample_date AS cur_date,
MIN(sample_date) OVER(
ORDER BY
sample_date ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING
) AS latest_date
FROM
LoadSample;
結果
sample_date | latest_date |
---|---|
2018-02-01 | |
2018-02-02 | 2018-02-01 |
2018-02-05 | 2018-02-02 |
2018-02-07 | 2018-02-05 |
2018-02-08 | 2018-02-07 |
2018-02-12 | 2018-02-08 |
1 行後にずらす
SELECT
sample_date AS cur_date,
MIN(sample_date) OVER(
ORDER BY
sample_date ASC ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING
) AS next_date
FROM
LoadSample;
結果
sample_date | next_date |
---|---|
2018-02-01 | 2018-02-02 |
2018-02-02 | 2018-02-05 |
2018-02-05 | 2018-02-07 |
2018-02-07 | 2018-02-08 |
2018-02-08 | 2018-02-12 |
2018-02-12 |

2.3 何もなし
ServerLoadSample
server | sample_date | load_val |
---|---|---|
A | 2018-02-01 | 1024 |
A | 2018-02-02 | 2366 |
A | 2018-02-05 | 2366 |
A | 2018-02-07 | 985 |
A | 2018-02-08 | 780 |
A | 2018-02-12 | 1000 |
B | 2018-02-01 | 54 |
B | 2018-02-02 | 39008 |
B | 2018-02-03 | 2900 |
B | 2018-02-04 | 556 |
B | 2018-02-05 | 12600 |
B | 2018-02-06 | 7309 |
C | 2018-02-01 | 1000 |
C | 2018-02-07 | 2000 |
C | 2018-02-16 | 500 |
SELECT
server,
sample_date,
SUM(load_val) OVER () AS sum_load
FROM
ServerLoadSample;
結果
server | sample_date | sum_load |
---|---|---|
A | 2018-02-01 | 74448 |
A | 2018-02-02 | 74448 |
A | 2018-02-05 | 74448 |
A | 2018-02-07 | 74448 |
A | 2018-02-08 | 74448 |
A | 2018-02-12 | 74448 |
B | 2018-02-01 | 74448 |
B | 2018-02-02 | 74448 |
B | 2018-02-03 | 74448 |
B | 2018-02-04 | 74448 |
B | 2018-02-05 | 74448 |
B | 2018-02-06 | 74448 |
C | 2018-02-01 | 74448 |
C | 2018-02-07 | 74448 |
C | 2018-02-16 | 74448 |
PARTITION BY
句がないため、ウィンドウ全体が 1 つのパーティションとして扱われる。
ORDER BY
句もないため、レコードを順序付けた累計的な計算は行われず、パーティション(= テーブル全行)に対して集約関数が適用される。

2.4 PARTITION BY
SELECT
server,
sample_date,
SUM(load_val) OVER (PARTITION BY server) AS sum_load
FROM
ServerLoadSample;
結果
server | sample_date | sum_load |
---|---|---|
A | 2018-02-01 | 8521 |
A | 2018-02-02 | 8521 |
A | 2018-02-05 | 8521 |
A | 2018-02-07 | 8521 |
A | 2018-02-08 | 8521 |
A | 2018-02-12 | 8521 |
B | 2018-02-01 | 62427 |
B | 2018-02-02 | 62427 |
B | 2018-02-03 | 62427 |
B | 2018-02-04 | 62427 |
B | 2018-02-05 | 62427 |
B | 2018-02-06 | 62427 |
C | 2018-02-01 | 3500 |
C | 2018-02-07 | 3500 |
C | 2018-02-16 | 3500 |
PARTITION BY
= GROUP BY
- 集約