MySQL の RANK()・DENSE_RANK()
ここでは MySQL の RANK() と DENSE_RANK() 関数ついてご説明します。
RANK() と DENSE_RANK() 関数は MySQL の Version 8.0 以降で使える関数です。
サンプルデータベースのテーブルを使いますので、実際にスクリプトを実行してみたい方は、こちら のスクリプトを実行して school_db データベースを作成しておいてください。
MySQL のRANK()・DENSE_RANK() 関数の使い方
MySQL の RANK()・DENSE_RANK() 関数を使うと、各行を指定した項目でランク付けをすることができます。
RANK()・DENSE_RANK() 関数 の使い方は同じで、RANK()・DENSE_RANK() に続けて OVER 句を指定します。
SELECT RANK() [OVER 句]
SELECT DENSE_RANK() [OVER 句]
OVER 句では、ORDER BY でどのカラムなどを使ってランク付けをするかを指定します。
グループ分けをして、その中でランク付けしたい場合は、PARTITION BY でグループ分けを指定できます。
たとえば、カラムA の降順で、各行をランク付けしたい時は次のように指定します。
SELECT RANK() OVER (ORDER BY カラムA DESC);
SELECT DENSE_RANK() OVER (ORDER BY カラムA DESC);
ソート順は ASC がデフォルトなので、昇順の時は指定しなくて大丈夫です。
複数のカラムを使ってランク付けしたい時は、ORDER BY カラムA, カラムB, ... のように指定できます。
また、カラムX の値でグループ分けして、その中でカラム A の値の降順でランク付けしたい時は次のように指定します。
SELECT RANK() OVER (PARTITION BY カラムX ORDER BY カラムA DESC);
SELECT DENSE_RANK() OVER (PARTITION BY カラムX ORDER BY カラムA DESC);
こちらも、複数のカラムでグルーピングしたい時は PARTITION BY カラムX, カラムY, ... のように指定できます。
RANK()・DENSE_RANK() の使い方は同じですが、違いはランクが同じレコードが複数存在する時に、続くランクの番号にギャップがあるかどうかです。
点数 | RANK | DENSE_RANK | |
---|---|---|---|
100 | 1 | 1 | |
95 | 2 | 2 | |
95 | 2 | 2 | |
95 | 2 | 2 | |
83 | 5 | 3 | RANK では 5、DENSE_RANK では 3 になる。 |
81 | 6 | 4 | |
81 | 6 | 4 | |
75 | 8 | 5 | RANK では 8、DENSE_RANK では 5 になる。 |
MySQL の RANK()・DENSE_RANK() でランク付けする
それでは、実際に RANK()・DENSE_RANK() 関数を使って連番を振ってみます。
次のような students テーブルがあります。
RANK()・DENSE_RANK() 関数を使って、誕生日の年の順にランク付けするには、次のようにできます。
SELECT RANK() OVER (ORDER BY YEAR(birthday)) AS rank_no,
DENSE_RANK() OVER (ORDER BY YEAR(birthday)) AS dense_rank_no,
student_id,
first_name,
last_name,
YEAR(birthday),
gender
FROM students;
[実行結果]
誕生日の年 YEAR(birthday) の順番でランク番号が振られています。
1 〜 4 番目のランク番号が同じで、先ほどご説明したように 5 番目のレコードのランク番号は、RANK() のほうは 5、DENSE_RANK() のほうは 2 になっていますね。
MySQL の RANK()・DENSE_RANK() でグループごとにランク付けする
続いて、RANK()・DENSE_RANK() 関数を使ってグループごとにランク付けしてみます。
先ほどの students テーブルのレコードを gender でグループ分けして、グループ内で誕生日の年の順にランク付けするには、次のようにできます。
SELECT RANK() OVER (PARTITION BY gender ORDER BY YEAR(birthday)) AS rank_no,
DENSE_RANK() OVER (PARTITION BY gender ORDER BY YEAR(birthday)) AS dense_rank_no,
student_id,
first_name,
last_name,
YEAR(birthday),
gender
FROM students;
[実行結果]
gender でグループ分けされてから、グループ内で誕生日の年の順にランク付けされています。
以上、MySQL の RANK() と DENSE_RANK() 関数ついてご説明しました。