SQLのウィンドウ関数|実務で使える集計テクニック

プログラミング言語

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には必須スキルです。