ウィンドウ関数(ROW_NUMBER・RANK・LAG・LEAD)

DS検定頻出のウィンドウ関数。PARTITION BY と OVER の使い方を実例でマスター。

DS検定で頻出のウィンドウ関数。集計と詳細を1クエリで両立できる強力ツール。

胡桃 あんず(普段) 胡桃 あんず

ウィンドウ関数って、どんな時に使うの?

若葉 みどり 先生(笑顔) 若葉 みどり 先生

集計値を出しつつ、元の各行もそのまま残したいときね。 例えば『各注文に、その顧客の累計購入額を並べたい』みたいなときよ。

白銀 ゆき(普段) 白銀 ゆき

代表的なウィンドウ関数: ROW_NUMBER(連番)、RANK(順位、同値はタイ)、DENSE_RANK(同値は同順位、次は連続)、LAG(前の行)、LEAD(次の行)。

-- 各カテゴリ内で売上トップ3を抽出
WITH ranked AS (
  SELECT
    order_id,
    category,
    amount,
    ROW_NUMBER() OVER (
      PARTITION BY category
      ORDER BY amount DESC
    ) AS rn
  FROM orders
)
SELECT order_id, category, amount
FROM ranked
WHERE rn <= 3;
桜井 もも(普段) 桜井 もも

OVER の中の PARTITION BYって、なんですかぁ?

白銀 ゆき(普段) 白銀 ゆき

GROUP BY のウィンドウ版だね。 『カテゴリごとに区切って、その中で順位を計算する』っていう指定。 ORDER BY と組み合わせると、区切りごとの並び順で順位がつくよ。

胡桃 あんず(普段) 胡桃 あんず

LAG・LEADは?

-- 各注文と1つ前の注文の差額を計算
SELECT
  order_id,
  customer_id,
  amount,
  LAG(amount) OVER (
    PARTITION BY customer_id
    ORDER BY ordered_at
  ) AS prev_amount,
  amount - LAG(amount) OVER (
    PARTITION BY customer_id
    ORDER BY ordered_at
  ) AS diff
FROM orders;
若葉 みどり 先生(普段) 若葉 みどり 先生

LAG で『前の行の値』を取ってきて、今の行との差分を計算しているのよ。 時系列データの分析でよく出てくるパターンね。

白銀 ゆき(普段) 白銀 ゆき

SUM OVER も便利で、累計を計算できるよ。 SUM(amount) OVER (PARTITION BY customer_id ORDER BY ordered_at) って書けば、『その顧客の累計購入額』が出せる。

桜井 もも(普段) 桜井 もも

RANK と DENSE_RANK の違いはなんですかぁ?

若葉 みどり 先生(普段) 若葉 みどり 先生

1位が2人いた場合ね。 RANK は次が3位(1, 1, 3, ...)、DENSE_RANK は次が2位(1, 1, 2, ...)になるのよ。 ROW_NUMBER は重複なしで一意(1, 2, 3, ...)ね。

白銀 ゆき(普段) 白銀 ゆき

DS検定★では、この3つの違いと、PARTITION BY の意味、それに LAG/LEAD のパターンが頻出だよ。

確認クイズ

ROW_NUMBER() OVER (PARTITION BY category ORDER BY amount DESC) の結果について正しいのはどれか。

  1. 全注文を金額降順で連番付け
  2. カテゴリごとに金額降順で連番付け
  3. カテゴリの数だけグループを作って合計を出す
  4. 注文を3つに分割する
こたえを見る

正解: 2. カテゴリごとに金額降順で連番付け

カテゴリごとに金額降順で連番付け。 PARTITION BY category でカテゴリで区切り、各カテゴリ内で amount 降順に1, 2, 3...と番号がつきます。 これがウィンドウ関数の典型的な使い方です。

若葉みどり先生・白銀ゆき・桜井もも・胡桃あんずのイラスト。海辺でビーチボール

この記事の関連書籍

Amazonアソシエイトリンクを含みます。他分野は おすすめ書籍ページ へ。

この記事について

データサイエンティスト検定スタディが作成した教材です。運営について・記事の作り方

試験についてはこちらをご覧ください: データサイエンティスト協会 公式サイト

この記事を共有