本文へスキップ
BecomeCoder

SQL データ操作 (DML)コース · 第7章 高度なクエリ · レッスン31

ウィンドウ関数① ― 順位をつける

ブラウザで完結

導入

「価格の高い順に順位を振りたい」。ORDER BY で並べ替えはできても、「1位・2位・3位…」という順位の番号そのものは付きません。これを一発で付けてくれるのが ウィンドウ関数 です。集計関数(SUM など)が複数行を1つにまとめてしまうのに対し、ウィンドウ関数は行を保ったまま、周りの行を見て計算します。

説明

順位付けの代表は ROW_NUMBER()RANK()DENSE_RANK() の3つ。いずれも OVER (ORDER BY ...) を付けて「どの順で番号を振るか」を指定します。

SELECT name, price,
  RANK() OVER (ORDER BY price DESC) AS 順位
FROM products;

OVER (...) の中の ORDER BY は、SELECT 全体の並び順とは別物で、「順位計算のための並び」を表します。3つの違いは、同じ値(同順位)が出たときの振る舞いです。

関数同じ値のとき例(100,100,90)
ROW_NUMBER()とにかく連番1, 2, 3
RANK()同順位で、次を飛ばす1, 1, 3
DENSE_RANK()同順位で、次を飛ばさない1, 1, 2

さらに強力なのが PARTITION BY です。「グループごとに順位を振り直す」指定で、たとえば「カテゴリごとの価格ランキング」が書けます。

SELECT category_id, name, price,
  RANK() OVER (PARTITION BY category_id ORDER BY price DESC) AS カテゴリ内順位
FROM products;
flowchart LR
    P["PARTITION BY category_id<br/>カテゴリで区切る"] --> O["ORDER BY price DESC<br/>各区切りの中で並べて順位を振る"]

やってみよう

初期表示のクエリを実行し、価格の高い順に順位が付くことを確認しましょう(ノートPCが1位)。次に上の PARTITION BY category_id の例を実行して、カテゴリごとに順位が 1 から振り直されることを見てください。RANK()ROW_NUMBER()DENSE_RANK() に変えて、違いも試しましょう。

演習

users を対象に、年齢の高い順の順位ROW_NUMBER() で振ってください。取り出す列は nameage と、順位の別名 順位

ヒント1を見る

ROW_NUMBER() OVER (ORDER BY age DESC) AS 順位

ヒント2を見る

SELECT name, age, ROW_NUMBER() OVER (ORDER BY age DESC) AS 順位 FROM users;

実際に動かしてみよう

下のエディタにクエリを書いて「実行」を押すと、ブラウザ内のSQLiteで結果が表示されます。本文の例をそのまま試したり、書き換えたりしてみましょう。

SQL — ブラウザ内で実行(SQLite)

ブラウザ内でSQLを動かす環境(SQLite)を読み込みます(初回のみ一瞬)。
スクロールして表示された時点でも自動で読み込まれます。