「rankとrow_numberってどう違うんだっけ?この状況ではどっちを使うべき…?」
と分からなくなって何度調べたことか笑
特にウィンドウ関数は、日常的に使っていても挙動を忘れがち。
そこで今回は、RANK
・ROW_NUMBER
・DENSE_RANK
の3つの違いについて、できるだけシンプルに・すぐ思い出せるように整理してみました。
同じように毎回調べている方の助けになればうれしいです。
1. まずは結論:違いをざっくり整理
関数名 | 重複値への対応 | 順位の飛び方 | ユースケース例 |
---|---|---|---|
ROW_NUMBER | 無視(毎行ユニーク) | 順位は飛ばない | 一意に順位をつけたいとき(サンプル抽出など) |
RANK | 同順位をつける | 順位が飛ぶ | スポーツの順位、コンテストの結果など |
DENSE_RANK | 同順位をつける | 順位は飛ばない | 商品の売上ランクなどで連番にしたいとき |
2. 実際のクエリで違いを見てみる
WITH sample_data AS (
SELECT 'A' AS item, 100 AS sales UNION ALL
SELECT 'B', 200 UNION ALL
SELECT 'C', 200 UNION ALL
SELECT 'D', 150
)
SELECT
item,
sales,
RANK() OVER (ORDER BY sales DESC) AS rank,
ROW_NUMBER() OVER (ORDER BY sales DESC) AS row_number,
DENSE_RANK() OVER (ORDER BY sales DESC) AS dense_rank
FROM sample_data;
▼ 実行結果
item | sales | rank | row_number | dense_rank |
---|---|---|---|---|
B | 200 | 1 | 1 | 1 |
C | 200 | 1 | 2 | 1 |
D | 150 | 3 | 3 | 2 |
A | 100 | 4 | 4 | 3 |
3. ざっくり覚えるための語感まとめ(暗記用)
- ROW_NUMBER: 行ごとに番号ふる。毎行違う → ユニークな番号。
- RANK: 順位をふるけど同率があると飛ばす。
- DENSE_RANK: 同率あっても詰めて連番でふる。
4. よくある使い方と注意点
✅ ROW_NUMBER の典型例
特定条件の最新データを1件だけ取得したいとき。
ユーザーごとの最新の購入日や購入内容など知りたい時に使えるので、これが一番使う!
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) AS rn
FROM access_logs
)
WHERE rn = 1
✅ RANK や DENSE_RANK の落とし穴
- 順位が欲しいだけなら
RANK
orDENSE_RANK
- でも、ORDER BY の方向(ASC/DESC)を間違うと、順位が逆になるので注意!
Comment