はじめに:データに「順番」をつけたいとき、どうしていますか?
-
「最新の投稿に番号を振りたい」
-
「同じカテゴリごとに1位・2位・3位とランキングしたい」
-
「複数条件で最初のデータだけを抽出したい」
こんな課題、あなたも感じたことありませんか?
MySQLでは、ROW_NUMBER()関数を使えば、データに「順番(連番)」を付けることができます。これは、データ分析・画面表示・業務帳票など、あらゆる実務で非常に役立つ機能です。
本記事では、ROW_NUMBER()の基本から応用までをわかりやすく、かつ実務的に解説します。
ROW_NUMBER()とは?|SQLウィンドウ関数の基本
ROW_NUMBER()の役割
ROW_NUMBER()は、データの並び順に応じて、連番(1, 2, 3…)を付けるウィンドウ関数です。
ROW_NUMBER() OVER (ORDER BY column_name)
-
OVER句内で指定したORDER BYの順序に従って番号が振られます。
-
結果はサブクエリやCTE(共通テーブル式)と一緒に使うことが多いです。
▼ 基本構文と実行例
以下は、ユーザーのログイン履歴に順番を付ける例です。
SELECT
user_id,
login_date,
ROW_NUMBER() OVER (ORDER BY login_date DESC) AS login_rank
FROM user_logins;
+---------+---------------------+-------------+
| user_id | login_date | login_rank |
+---------+---------------------+-------------+
| 101 | 2024-12-15 10:00:00 | 1 |
| 101 | 2024-12-14 08:30:00 | 2 |
| 102 | 2024-12-13 09:15:00 | 3 |
+---------+---------------------+-------------+
→ 最新のログインから順に1位・2位…と並ぶようになります。
グループごとに順位をつけるには?|PARTITION BYの活用
目的別に順位をつける
例えば、「ユーザーごとのログイン回数を1位から数えたい」というケースでは、PARTITION BY句を使います。
SELECT
user_id,
login_date,
ROW_NUMBER() OVER (
PARTITION BY user_id
ORDER BY login_date DESC
) AS user_rank
FROM user_logins;
図解テキスト
【ROW_NUMBERのイメージ】
[user_idでグループ化]
↓
[login_dateでソート]
↓
[各グループ内で1〜Nを付与]
サブクエリで「最新1件だけ」を取り出す
ROW_NUMBER()をサブクエリと組み合わせると、「グループごとに最新の1件だけ抽出する」ことも可能です。
SELECT *
FROM (
SELECT
user_id,
login_date,
ROW_NUMBER() OVER (
PARTITION BY user_id
ORDER BY login_date DESC
) AS rn
FROM user_logins
) AS ranked
WHERE rn = 1;
→ ユーザーごとに最新ログイン1件を取得できます。
よくあるつまずき|ROW_NUMBER()の落とし穴と解決法
間違った実装例:GROUP BYとの併用で意図しない結果に
SELECT
user_id,
MAX(login_date),
ROW_NUMBER() OVER (ORDER BY login_date DESC)
FROM user_logins
GROUP BY user_id;
-
ROW_NUMBER()とGROUP BYを同時に使うと不整合になりがちです。
-
グループ化した時点で、ROW_NUMBERの前提(行単位での並び)が崩れます。
正しい実装:サブクエリやCTEで分離
WITH ranked_logins AS (
SELECT
user_id,
login_date,
ROW_NUMBER() OVER (
PARTITION BY user_id
ORDER BY login_date DESC
) AS rn
FROM user_logins
)
SELECT * FROM ranked_logins WHERE rn = 1;
→ ロジックを明確に分けることで、意図通りのデータが得られます。
まとめ:ROW_NUMBER()を使いこなすために
記事のポイント再確認
-
ROW_NUMBER():並び順に応じて連番を振るウィンドウ関数
-
PARTITION BY:グループごとの連番を付ける
-
ORDER BY:並び順の基準を定める
-
サブクエリ / CTE:抽出条件と組み合わせる際の定番テクニック
ROW_NUMBER()を用いた実行環境を使いたい方は
-
ローカルのMySQL環境(8.0以降)
-
オンラインSQL実行サービス
-
Dockerで簡単構築できるMySQLイメージ
などで試してみてください。
【外部リンク】
MySQL 公式ドキュメント: Window Functions
SQL Tutorial: ROW_NUMBER() 関数の使い方