いかおくら自習室のブログ

普段の学習内容などのアウトプット用のブログです

RANK関数の基本的な使い方

はじめに

あまりRANK関数を記述する機会がないので いざ書こうとなると検索しては試してエラー、、の繰り返し、、 基本的な内容に絞ってまとめておきます

準備

CREATE TABLE students (
  id INT,
  name VARCHAR(255),
  classes VARCHAR(255),
  subject VARCHAR(255),
  score INT
);

INSERT INTO students (id, name, classes, subject, score)
VALUES
  (1, '田中 太郎', 'A組', '数学', 80),
  (2, '鈴木 花子', 'A組', '理科', 90),
  (3, '佐藤 次郎', 'B組', '数学', 70),
  (4, '高橋 さやか', 'B組', '理科', 85),
  (5, '山田 菜々子', 'C組', '数学', 75),
  (6, '中村 美穂', 'C組', '理科', 92),
  (7, '小林 大輔', 'D組', '数学', 68),
  (8, '加藤 美佐子', 'D組', '理科', 87),
  (9, '吉田 智子', 'E組', '数学', 72),
  (10, '山口 恵美', 'E組', '理科', 94);

書き方

SELECT
name
,score
,RANK() OVER (ORDER BY score DESC) AS score_rank
FROM students;

-- 出力結果
  name     | subject | score |  score_rank
-----------+---------+-------+------------
山口 恵美     理科      94         1
中村 美穂     理科      92         2
鈴木 花子     理科      90         3
加藤 美佐子    理科      87         4
高橋 さやか    理科      85         5
田中 太郎     数学      80         6
山田 菜々子    数学      75         7
吉田 智子     数学      72         8
佐藤 次郎     数学      70         9
小林 大輔     数学      68         10

これで点数が高い順に並べることができました。 ただ実際には、科目(subject)ごとの順位で分けるべきなので 科目ごとのランクを記述するのが以下です。

SELECT
name
,subject
,score
,RANK() OVER (PARTITION BY subject ORDER BY score DESC) AS score_rank
FROM students;

-- 出力結果
  name     | subject | score |  score_rank
-----------+---------+-------+------------
田中 太郎     数学      80         1
山田 菜々子    数学      75         2
吉田 智子     数学      72         3
佐藤 次郎     数学      70         4
小林 大輔     数学      68         5
山口 恵美     理科      94         1
中村 美穂     理科      92         2
鈴木 花子     理科      90         3
加藤 美佐子    理科      87         4
高橋 さやか    理科      85         5

これで科目ごとの順位をつけることができました。 PARTITION BYでGROUP BYと似たような動きができます。 科目(subject)ごとに、点数(score)を高い順位に並び替え(ORDER BY + DESC)ています。

追記(2023/03/07)

似ている関数にROW_NUMBERがあります。 区分けは以下

  • RANK:等しい値があった場合、同一順位をつける
  • ROW_NUMBER:等しい値があった場合、別順位をつける

同点の生徒がいるようにstudentsテーブルを以下に修正して挙動を見てみます。

DROP TABLE students;

INSERT INTO students (id, name, classes, subject, score)
VALUES
  (1, '田中 太郎', 'A組', '数学', 80),
  (2, '鈴木 花子', 'A組', '理科', 90),
  (3, '佐藤 次郎', 'B組', '数学', 80),
  (4, '高橋 さやか', 'B組', '理科', 85),
  (5, '山田 菜々子', 'C組', '数学', 75),
  (6, '中村 美穂', 'C組', '理科', 92),
  (7, '小林 大輔', 'D組', '数学', 80),
  (8, '加藤 美佐子', 'D組', '理科', 87),
  (9, '吉田 智子', 'E組', '数学', 72),
  (10, '山口 恵美', 'E組', '理科', 90);
RANK関数の場合
SELECT
name
,subject
,score
,RANK() OVER (PARTITION BY subject ORDER BY score DESC) AS score_rank
FROM students;

-- 出力結果
  name     | subject | score |  score_rank
-----------+---------+-------+------------
田中 太郎     数学      80         1
佐藤 次郎     数学      80         1
小林 大輔     数学      80         1
山田 菜々子    数学      75         4
吉田 智子     数学      72         5
中村 美穂     理科      92         1
鈴木 花子     理科      90         2
山口 恵美     理科      90         2
加藤 美佐子    理科      87         4
高橋 さやか    理科      85         5
ROW_NUMBER関数の場合
SELECT
name
,subject
,score
,ROW_NUMBER() OVER (PARTITION BY subject ORDER BY score DESC) AS score_rank
FROM students;

-- 出力結果
  name     | subject | score |  score_rank
-----------+---------+-------+------------
田中 太郎     数学      80         1
佐藤 次郎     数学      80         2
小林 大輔     数学      80         3
山田 菜々子    数学      75         4
吉田 智子     数学      72         5
中村 美穂     理科      92         1
鈴木 花子     理科      90         2
山口 恵美     理科      90         3
加藤 美佐子    理科      87         4
高橋 さやか    理科      85         5