Think Twice
IT技術メモ | SQL Serverのメモ
Created: 2021-02-15 / Updated: 2021-02-15

SQL ServerのRANK, DENSE_RANK, ROW_NUMBERの違い


※メモの中で出てくる人物名は仮名です。たまたま同性同名の方がいらっしゃいましたらごめんなさい。

目次


RANKとDENSE_RANKとROW_NUMBERの振る舞い

RANKとDENSE_RANKとROW_NUMBERはそれぞれ似ているけどちょっとだけ違うので違いをメモしておきます。

データ

以下のようなデータを持つテーブルUserがあるとします。

Name Age Score
川村 千治 39 70
北島 永寿 43 80
永田 祐美 27 80
三上 なつみ 18 75
野中 玲奈 32 100

Scoreについて、RANKDENSE_RANKROW_NUMBERをそれぞれ取得すると以下のようになります。

SQL
Copy
SELECT [Name]
      ,[Age]
      ,[Score]
      ,RANK() OVER(ORDER BY Score) AS RANK
      ,DENSE_RANK() OVER(ORDER BY Score) AS DENSE_RANK
      ,ROW_NUMBER() OVER(ORDER BY Score) AS ROW_NUMBER
FROM [dbo].[User]

取得結果

Name Age Score RANK DENSE_RANK ROW_NUMBER
川村 千治 39 70 1 1 1
北島 永寿 43 80 3 3 3
永田 祐美 27 80 3 3 4
三上 なつみ 18 75 2 2 2
野中 玲奈 32 100 5 4 5

それぞれは以下のような特徴がある。

PARTITION BY句で区切って順位付けする

RANKとDENSE_RANKとROW_NUMBERの振る舞いで使ったテーブルをちょっと加工して、
以下のようなデータを持つテーブルUserを準備します。

Name Age Score Class
川村 千治 39 70 A
永田 祐美 27 80 A
野中 玲奈 32 100 A
増田 保平 22 50 B
上原 さゆみ 27 70 B
浅井 れいや 33 80 B
竹中 沙耶香 24 60 C
三上 なつみ 20 60 C
緒方 利浩 18 60 C
北島 永寿 43 80 C

このデータについて、Class別に順位付けしたい場合、以下のようにOVER句の中で、PARTITION BYで区切りたい列を指定します。

SQL
Copy
SELECT [Name]
      ,[Age]
      ,[Score]
      ,[Class]
      ,RANK() OVER(PARTITION BY Class ORDER BY Score) AS RANK
      ,DENSE_RANK() OVER(PARTITION BY Class ORDER BY Score) AS DENSE_RANK
      ,ROW_NUMBER() OVER(PARTITION BY Class ORDER BY Score, Age DESC) AS ROW_NUMBER
FROM [dbo].[User]
ORDER BY [Class], [Score]

取得結果

Name Age Score Class RANK DENSE_RANK ROW_NUMBER
川村 千治 39 70 A 1 1 1
永田 祐美 27 80 A 2 2 2
野中 玲奈 32 100 A 3 3 3
増田 保平 22 50 B 1 1 1
上原 さゆみ 27 70 B 2 2 2
浅井 れいや 33 80 B 3 3 3
竹中 沙耶香 24 60 C 1 1 1
三上 なつみ 20 60 C 1 1 2
緒方 利浩 18 60 C 1 1 3
北島 永寿 43 80 C 4 2 4

参考

参考サイト