Open4

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

churuchuruchuruchuru

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
)
;
churuchuruchuruchuru

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
churuchuruchuruchuru

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 句もないため、レコードを順序付けた累計的な計算は行われず、パーティション(= テーブル全行)に対して集約関数が適用される。

churuchuruchuruchuru

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 - 集約