SQL Serverでデータの順位付けやランキング処理を行う場合、ROW_NUMBER、RANK、DENSE_RANKという3つのウィンドウ関数がよく利用されます。どれも順位を付けるための関数ですが、同順位が発生した場合の順位の扱いに大きな違いがあります。この記事では、それぞれの特徴や使い分け方を具体例を交えながら解説します。
SQL ServerのROW_NUMBER・RANK・DENSE_RANKとは
ROW_NUMBER、RANK、DENSE_RANKはいずれもSQL Serverで利用できるウィンドウ関数で、検索結果に連番や順位を付与するために使用します。
通常のORDER BYでは単純に並び替えるだけですが、ウィンドウ関数を使うことで、各行に対して順位情報を追加した状態でデータを取得できます。
例えば、売上データから「売上金額が高い順に順位を付けたい」「同じ売上の場合は同順位にしたい」といった処理を簡単に実現できます。
ROW_NUMBER関数の特徴と使い方
ROW_NUMBER関数は、指定した順番に対して重複しない連続した番号を付ける関数です。同じ値が存在していても、必ず異なる番号が割り当てられます。
基本的な構文は以下のようになります。
SELECT
商品名,
売上金額,
ROW_NUMBER() OVER(ORDER BY 売上金額 DESC) AS 順位
FROM 売上テーブル;
例えば以下のような売上データがある場合を考えます。
| 商品 | 売上 |
|---|---|
| A商品 | 10000 |
| B商品 | 8000 |
| C商品 | 8000 |
| D商品 | 5000 |
ROW_NUMBERを使用すると、結果は「1位、2位、3位、4位」のように必ず異なる番号になります。同じ売上金額でも順位が分かれる点が特徴です。
例えば、ページング処理で「検索結果の1件目から20件目を取得する」といった用途ではROW_NUMBERがよく利用されます。
RANK関数の特徴と順位の飛び方
RANK関数は、同じ値の場合に同じ順位を付けます。ただし、同順位が発生した場合、その次の順位が飛ぶという特徴があります。
先ほどの売上データでRANKを使用すると以下のようになります。
| 商品 | 売上 | 順位 |
|---|---|---|
| A商品 | 10000 | 1位 |
| B商品 | 8000 | 2位 |
| C商品 | 8000 | 2位 |
| D商品 | 5000 | 4位 |
8000円の商品が2つあるため、2位が2件存在し、その次の順位は3位ではなく4位になります。
スポーツ大会の順位表のように「同率2位が複数存在した場合、次は4位になる」というルールを表現したい場合にRANKが適しています。
DENSE_RANK関数の特徴とRANKとの違い
DENSE_RANK関数もRANKと同じように同じ値には同じ順位を付けます。しかし、RANKと違って順位番号が飛びません。
同じ売上データでDENSE_RANKを使用すると以下のようになります。
| 商品 | 売上 | 順位 |
|---|---|---|
| A商品 | 10000 | 1位 |
| B商品 | 8000 | 2位 |
| C商品 | 8000 | 2位 |
| D商品 | 5000 | 3位 |
8000円の商品が同率2位になりますが、その次の商品は3位になります。順位の抜けが発生しないことがDENSE_RANKの特徴です。
例えば、売上ランキングで「第1グループ、第2グループ、第3グループ」のように順位グループを作成したい場合にはDENSE_RANKが向いています。
ROW_NUMBER・RANK・DENSE_RANKの違いを比較
3つの関数の違いを整理すると以下のようになります。
| 関数 | 同順位 | 順位の飛び | 主な用途 |
|---|---|---|---|
| ROW_NUMBER | 発生しない | なし | 一意の連番付与、ページング |
| RANK | 同順位になる | あり | 競技順位、ランキング |
| DENSE_RANK | 同順位になる | なし | 順位グループ作成 |
どの関数を使うかは、「同じ値の場合に同じ順位にしたいか」「順位を飛ばす必要があるか」で判断すると分かりやすくなります。
PARTITION BYを使ったグループ別ランキング
ウィンドウ関数ではPARTITION BYを組み合わせることで、グループごとの順位付けも可能です。
例えば、店舗ごとに売上ランキングを作成する場合は以下のように記述します。
SELECT
店舗名,
商品名,
売上金額,
RANK() OVER(PARTITION BY 店舗名 ORDER BY 売上金額 DESC) AS 順位
FROM 売上テーブル;
この場合、店舗ごとに順位が1位から振り直されます。全国ランキングではなく、店舗別ランキングや部署別ランキングなどを作成するときに便利です。
実務でのROW_NUMBER・RANK・DENSE_RANKの選び方
実際のシステム開発では、目的に応じて関数を選択することが重要です。
例えば、社員一覧から「登録日時が新しい順に番号を付けて最新データだけ取得する」といった処理ではROW_NUMBERが適しています。
一方で、商品ランキングや評価順位のように同じ点数や金額を同じ順位として扱いたい場合はRANKまたはDENSE_RANKを利用します。順位の欠番を許容するかどうかで使い分けることがポイントです。
まとめ
SQL ServerのROW_NUMBER、RANK、DENSE_RANKは、どれもデータに順位を付けるための便利なウィンドウ関数ですが、同順位の扱いに違いがあります。
ROW_NUMBERは必ず一意の番号を付けたい場合、RANKは同順位を作りつつ順位の飛びを許容する場合、DENSE_RANKは同順位を作りながら連続した順位を維持したい場合に適しています。
ランキング表示、データ分析、ページング処理などSQL Serverでは頻繁に利用される機能なので、それぞれの違いを理解して目的に合わせて使い分けることが、効率的なSQL設計につながります。


コメント