同順位におけるRANKとDENSE_RANKの違い
値が同じ場合の、順位の飛び番と飛び番なしの違いを問う定番問題を学びます。
「同順位におけるRANKとDENSE_RANKの違い」はCoddyKit上の無料SQL Interview Prepレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSQL Interview Prep学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 SQL Interview Prepコースには全4レッスンが含まれています。
3つのランキング関数を比較する
SQLには3つのランキング用ウィンドウ関数があります。ウィンドウ関数について最もよく聞かれる質問は、同順位をどう扱うかの違いです。
- ROW_NUMBER — 常に一意です。同順位の行にも、任意の異なる番号が付けられます。
- RANK — 同順位には同じ順位を付け、その次の順位を飛ばします(欠番が生じます)。
- DENSE_RANK — 同順位には同じ順位を付け、その次の順位を飛ばしません(欠番が生じません)。
この違いをすぐに説明できることは、面接で確かな評価材料になります。
具体的な例のテーブル
5つのスコアを降順に並べたとします。100, 90, 90, 80, 70 です。各関数がどのように番号を付けるか見てみましょう。
- ROW_NUMBER:1, 2, 3, 4, 5
- RANK:1, 2, 2, 4, 5(同順位の後で3を飛ばします)
- DENSE_RANK:1, 2, 2, 3, 4(飛ばしません)
この100/90/90/80/70の例を覚えておけば、この質問にその場で答えられます。
SELECT
score,
ROW_NUMBER() OVER (ORDER BY score DESC) AS rownum,
RANK() OVER (ORDER BY score DESC) AS rnk,
DENSE_RANK() OVER (ORDER BY score DESC) AS dense
FROM scores;RANK が欠番を作る仕組み
RANK は、順序においてその行より厳密に前にある行の数に1を加えた値を、各行の順位として割り当てます。値90の2行は、前にある行が1行(100)だけなので、どちらも順位2になります。次に来るより小さい値の前には3行あるため、順位は4に飛びます。
このため、RANK は競技の順位付けに似ています。同率の銀メダリストが複数いて、銅メダリストがいない状態です。
-- scores 100,90,90,80 -> RANK = 1,2,2,4
SELECT score, RANK() OVER (ORDER BY score DESC) AS rnk
FROM scores;DENSE_RANK が欠番を避ける仕組み
DENSE_RANK は、現在の値より前にある異なる値の数に1を加えた値を順位として割り当てます。90の同順位の後、80より前にある異なる値は100と90の2つだけなので、80の順位は3となり、欠番は生じません。
同順位を1つとして数える「2番目に高い給与」のように、異なる値の順位が重要な場合は DENSE_RANK を使います。
-- scores 100,90,90,80 -> DENSE_RANK = 1,2,2,3
SELECT score, DENSE_RANK() OVER (ORDER BY score DESC) AS dense
FROM scores;各関数の選び方
面接官が好む、すぐに判断できる指針です。
- 位置ごとに必ず1行だけ必要ですか(最新レコード、ページネーションなど)? → ROW_NUMBER を使います。
- 同順位を同じ順位として扱い、順位の飛び番も正しくしたいですか(スポーツのランキング、同順位を含む上位3位など)? → RANK を使います。
- N番目の異なる値が必要ですか(N番目に高い給与など)? → DENSE_RANK を使います。
誤った選択をすると返される行が変わるため、選んだ理由を声に出して説明してください。
パーティション内でのランキング
3つの関数はすべて PARTITION BY を受け取り、各グループ内で独立して順位付けできます。各パーティションでは順位が1から始まります。
ここでは、各部署が所属する従業員を給与順に順位付けし、同順位を DENSE_RANK で処理しています。各部署で最も給与の高い従業員は順位1となり、同じ給与の従業員は同じ順位になります。
SELECT
department,
name,
salary,
DENSE_RANK() OVER (
PARTITION BY department
ORDER BY salary DESC
) AS salary_rank
FROM employees;実例:同順位を含む上位3件
「部署ごとに給与の上位3つを返し、3位が複数人の同順位なら全員を含めてください。」これは ROW_NUMBER ではなく、RANK または DENSE_RANK が必要です。
DENSE_RANK <= 3 を使うと、給与額の上位3つの異なる水準と、その水準に該当するすべての従業員が残ります。これが「同順位を含める」という意味です。
SELECT department, name, salary, salary_rank
FROM (
SELECT department, name, salary,
DENSE_RANK() OVER (
PARTITION BY department ORDER BY salary DESC
) AS salary_rank
FROM employees
) t
WHERE salary_rank <= 3;実例:2番目に高い給与
SQL面接で最も有名な質問です。堅牢な解答では DENSE_RANK を使うため、最高給与が重複していても、本当の2番目の値が除外されません。
3人が最高給与を得ている場合でも、DENSE_RANK = 2 は次に高い異なる給与を正しく特定します。一方、ROW_NUMBER = 2 では、別の最高給与の従業員が返されるだけです。
SELECT DISTINCT salary AS second_highest
FROM (
SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS dr
FROM employees
) t
WHERE dr = 2;「N番目に高い値」におけるRANKとDENSE_RANKの違い
N番目に高い値を求める問題で、なぜ RANK ではなく DENSE_RANK を使うのでしょうか。RANK では順位に飛び番が生じるためです。給与が100、100、90の場合、90の RANK は3ですが、DENSE_RANK は2です。
質問が「2番目に高い異なる給与」を求めている場合、RANK = 2 で絞り込むと何も返りません。一方、DENSE_RANK = 2 なら90を正しく返します。「N番目の異なる値」は必ず DENSE_RANK に対応付けてください。
-- salaries 100,100,90
-- RANK: 1,1,3 -> WHERE rank = 2 returns NOTHING
-- DENSE_RANK: 1,1,2 -> WHERE dense_rank = 2 returns 90SQL方言ごとの注意点
良い知らせがあります。ROW_NUMBER、RANK、DENSE_RANK はSQL標準であり、PostgreSQL、SQL Server、Oracle、MySQL 8以降、BigQuery、Snowflakeで同じように動作します。ここで説明した同順位の扱いも共通です。
関連する関数として PERCENT_RANK があります。これは RANK を基に、0から1までの相対的な位置を返します。面接官からパーセンタイルランキングについて聞かれた場合は、言及する価値があります。
よくある間違い
次の点に注意してください。
- 「N番目に高い値」を求める際に
ROW_NUMBERを使い、同順位の行を取りこぼす。 - 異なる値を意味する質問で
RANKを使い、飛び番のために結果が空になる。 OVER内のORDER BYを忘れる。これがなければランキングに意味はありません。- ランキングを外側のクエリではなく、
WHEREで直接絞り込もうとする。
理解度チェック
同順位のルールを適用してください。
まとめ:飛び番ありと飛び番なし
これで、適切なランキング関数をすぐに選べるようになりました。
- ROW_NUMBER:一意の番号を付け、同じ順位はありません。
- RANK:同順位は同じ順位になり、その後に飛び番が生じます(1,2,2,4)。
- DENSE_RANK:同順位は同じ順位になりますが、飛び番は生じません(1,2,2,3)。
- 「N番目に高い異なる値」 →
DENSE_RANK、「同順位を含む上位N件」 →RANK/DENSE_RANK、「位置ごとに1行」 →ROW_NUMBERです。
次は、ウィンドウ関数の結果を実際に絞り込む方法です。WHERE では絞り込めないためです。
よくある質問
「同順位におけるRANKとDENSE_RANKの違い」レッスンは無料ですか?
はい。「同順位におけるRANKとDENSE_RANKの違い」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、SQL Interview Prepコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 SQL Interview Prepコースには全4レッスンが含まれています。
「同順位におけるRANKとDENSE_RANKの違い」で何を学びますか?
値が同じ場合の、順位の飛び番と飛び番なしの違いを問う定番問題を学びます。 ブラウザで直接実行するハンズオンコードでSQL Interview Prepを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
SQL Interview Prepを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSQL Interview Prepは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「同順位におけるRANKとDENSE_RANKの違い」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSQL Interview Prepレッスンでコードを書いて実行できますか?
はい。すべてのSQL Interview Prepレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- OVER、PARTITION BY、ORDER BY
- ROW_NUMBERで一意の連番を付ける
- 同順位におけるRANKとDENSE_RANKの違い
- ウィンドウ関数の結果でフィルタリングする