SQLWindow関数とは?〜実行順ごとに解説〜

目次

はじめに

Window関数とは、ウィンドウと呼ばれる範囲のレコードに対して集計や演算を行う関数です。

使用データ

emplyeeテーブル

idnamedepartmentsalaryhire_date
1田中 太郎営業部450000.02018-04-01
2鈴木 花子営業部520000.02016-04-01
3佐藤 次郎営業部380000.02020-04-01
4高橋 美咲開発部600000.02015-04-01
5伊藤 健一開発部550000.02017-04-01
6渡辺 由美開発部480000.02019-04-01
7山本 大輔人事部500000.02014-04-01
8中村 さくら人事部420000.02021-04-01

daily_salesテーブル

datesales
2025-05-01120000.0
2025-05-02135000.0
2025-05-0398000.0
2025-05-04142000.0
2025-05-05158000.0
2025-05-06110000.0
2025-05-07125000.0

GROUP BYとの相違点

Window関数と同じようにレコードをグループ化するGROUP BY関数とどこが異なるのでしょうか?

ここではemployeesテーブルにdepartmentごとに平均賃金を追加したい時を考えてみます。

GROUP BY関数を使用する場合だと、複数の行を一つにまとめて後でemployeeテーブルと結合しなくていけません。

departmentAVG(salary)
営業部450000.0
開発部543333.333333
人事部460000.0

一方、Window関数は元のレコードを残したまま、各レコードに対して集計結果を付与します。

namedepartmentsalarydept_avg
山本 大輔人事部500000.0460000.0
中村 さくら人事部420000.0460000.0
田中 太郎営業部450000.0450000.0
鈴木 花子営業部520000.0450000.0
佐藤 次郎営業部380000.0450000.0
高橋 美咲開発部600000.0543333.333333
伊藤 健一開発部550000.0543333.333333
渡辺 由美開発部480000.0543333.333333

この時使用しているクエリ

SELECT name, department, salary,
       AVG(salary) OVER (PARTITION BY department) AS dept_avg
FROM employees;

AVG(salary) OVER (PARTITION BY department)がWindow関数の部分でPARTITION BYがグループ分けする基準(部門ごと、顧客ごとなど)を示します。

ランキング系の関数

ウィンドウの中での順位知りたい場合に使用します。

主な関数として

  • ROW_NUMBER() — 連番(1, 2, 3, 4…)
  • RANK() — 同順位あり、次は飛ぶ(1, 2, 2, 4…)
  • DENSE_RANK() — 同順位あり、次は飛ばない(1, 2, 2, 3…

実用例

部門内の給与ランキング

SELECT name, department, salary,
       RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS salary_rank
FROM employees;

department基準でグループ分けした際(PARTITION BY department)、降順で順位づけします(RANK() …. ORDER BY salary DESC)

namedepartmentsalarysalary_rank
山本 大輔人事部500000.01
中村 さくら人事部420000.02
鈴木 花子営業部520000.01
田中 太郎営業部450000.02
佐藤 次郎営業部380000.03
高橋 美咲開発部600000.01
伊藤 健一開発部550000.02
渡辺 由美開発部480000.03

前後参照系の関数

ウィンドウの中での前後の比較をしたい場合の使用します。

主な関数として

  • LAG(列, n) — n行前の値
  • LEAD(列, n) — n行後の値
  • FIRST_VALUE(), LAST_VALUE() — 最初/最後の値

実用例

前日比売上

SELECT date, sales,
       sales - LAG(sales, 1) OVER (ORDER BY date) AS diff_from_prev
FROM daily_sales;

日付順で並べたとき(ORDER BY date)、1つ前のレコードのsales値(LAG(sales, 1))。つまりsales - LAG(sales, 1) OVER (ORDER BY date) は昨日に比べてどのくらい売り上げが伸びているかを表す。

datesalesdiff_from_prev
2025-05-01120000.0null
2025-05-02135000.015000.0
2025-05-0398000.0-37000.0
2025-05-04142000.044000.0
2025-05-05158000.016000.0
2025-05-06110000.0-48000.0
2025-05-07125000.015000.0

集計系の関数

データの特徴を見たいときに使用する

主な関数としてSUM(), AVG(), COUNT(), MAX(), MIN()

実用例

移動平均(直近3日)

SELECT date, sales,
       AVG(sales) OVER (ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM daily_sales;

日付順に並べて(ORDER BY date)、2行前から(ROWS BETWEEN 2 PRECEDING)、現在の行まで(CURRENT ROW)をウィンドウの対象として、その平均を計算します。

datesalesmoving_avg
2025-05-01120000.0120000.0
2025-05-02135000.0127500.0
2025-05-0398000.0117666.666667
2025-05-04142000.0125000.0
2025-05-05158000.0132666.666667
2025-05-06110000.0136666.666667
2025-05-07125000.0131000.0

まとめ

このようにWindow関数を使用できるようになれば長く複雑なクエリをかく必要がなくなったり、より直感的にクエリのかけるようになるので是非使いこなしてみてください。

CTA
  • URLをコピーしました!
  • URLをコピーしました!
この記事を書いた人
目次