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() の使い方は同じですが、違いはランクが同じレコードが複数存在する時に、続くランクの番号にギャップがあるかどうかです。

点数RANKDENSE_RANK
10011
9522
9522
9522
8353RANK では 5、DENSE_RANK では 3 になる。
8164
8164
7585RANK では 8、DENSE_RANK では 5 になる。

MySQL の RANK()・DENSE_RANK() でランク付けする

それでは、実際に RANK()・DENSE_RANK() 関数を使って連番を振ってみます。

次のような students テーブルがあります。

MySQL の MySQL の RANK()・DENSE_RANK() 1


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;

[実行結果]

MySQL の MySQL の RANK()・DENSE_RANK() 2

誕生日の年 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;

[実行結果]

MySQL の MySQL の RANK()・DENSE_RANK() 3

gender でグループ分けされてから、グループ内で誕生日の年の順にランク付けされています。


以上、MySQL の RANK() と DENSE_RANK() 関数ついてご説明しました。

© 2024 MySQL 入門