0Pricing
SQL Interview Prep · レッスン

同順位における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 90

SQL方言ごとの注意点

良い知らせがあります。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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. OVER、PARTITION BY、ORDER BY
  2. ROW_NUMBERで一意の連番を付ける
  3. 同順位におけるRANKとDENSE_RANKの違い
  4. ウィンドウ関数の結果でフィルタリングする
← SQL Interview Prepに戻る