SQLのウィンドウ関数は、行をグループ化せずに「他の行を参照して集計」できる強力な機能です。ランキング・累積・移動平均など、従来GROUP BYでは表現しにくかった処理が一発で書けます。本記事では、実務で使えるウィンドウ関数を解説します。
基本構文
関数名(...) OVER (
[PARTITION BY ...]
[ORDER BY ...]
[ROWS | RANGE ...]
)
1. ROW_NUMBER(行番号)
SELECT
name, score,
ROW_NUMBER() OVER (ORDER BY score DESC) AS rank
FROM students;
2. RANK / DENSE_RANK
SELECT
name, score,
RANK() OVER (ORDER BY score DESC) AS r, -- 同点は同順位、次は飛ぶ
DENSE_RANK() OVER (ORDER BY score DESC) AS dr -- 同点は同順位、次は連番
FROM students;
3. PARTITION BY(グループ内ランキング)
-- クラスごとの上位3名
SELECT * FROM (
SELECT
class_id, name, score,
ROW_NUMBER() OVER (PARTITION BY class_id ORDER BY score DESC) AS rk
FROM students
) t
WHERE rk <= 3;
4. LAG / LEAD(前後行参照)
SELECT
date, sales,
LAG(sales) OVER (ORDER BY date) AS prev_sales,
sales - LAG(sales) OVER (ORDER BY date) AS diff
FROM daily_sales;
5. SUM/AVG OVER(累積・移動平均)
-- 累積売上
SELECT
date, sales,
SUM(sales) OVER (ORDER BY date) AS cumulative
FROM daily_sales;
-- 直近7日の移動平均
SELECT
date, sales,
AVG(sales) OVER (
ORDER BY date
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
) AS ma7
FROM daily_sales;
6. FIRST_VALUE / LAST_VALUE
SELECT
user_id, login_date,
FIRST_VALUE(login_date) OVER (
PARTITION BY user_id ORDER BY login_date
) AS first_login
FROM logins;
7. NTILE(N等分)
-- スコアで4分位グループ
SELECT
name, score,
NTILE(4) OVER (ORDER BY score DESC) AS quartile
FROM students;
パフォーマンスのコツ
- ORDER BYのカラムにインデックス
- PARTITION BYで処理対象を絞る
- 巨大データ+複雑なウィンドウはマテリアライズドビューも検討
まとめ
ウィンドウ関数は「グループ化せずに集計や順位付けができる」SQLの強力な道具です。ROW_NUMBER・SUM OVER・LAG/LEADを覚えるだけで、複雑な分析クエリがシンプルに書けるようになります。実務で頻出するBI・レポート系のSQLには必須スキルです。