MYSQL实现分组排名和不分组排名(函数RANK,DENSE_RANK和ROW_NUMBER)

目录

  • [1. 排名分类](#1. 排名分类)
    • [1.1 区别RANK,DENSE_RANK和ROW_NUMBER](#1.1 区别RANK,DENSE_RANK和ROW_NUMBER)
    • [1.2 分组排名](#1.2 分组排名)
  • [2. 准备数据](#2. 准备数据)
  • [3. 不分组排名](#3. 不分组排名)
    • [3.1 连续排名](#3.1 连续排名)
    • [3.2 并列跳跃排名](#3.2 并列跳跃排名)
    • [3.3 并列连续排名](#3.3 并列连续排名)
  • [4. 分组排名](#4. 分组排名)
    • [4.1 分组连续排名](#4.1 分组连续排名)
    • [4.2 分组并列跳跃排名](#4.2 分组并列跳跃排名)
    • [4.3 分组并列连续排名](#4.3 分组并列连续排名)

1. 排名分类

1.1 区别RANK,DENSE_RANK和ROW_NUMBER

  • RANK并列跳跃排名,并列即相同的值,相同的值保留重复名次,遇到下一个不同值时,跳跃到总共的排名
  • DENSE_RANK并列连续排序,并列即相同的值,相同的值保留重复名次,遇到下一个不同值时,依然按照连续数字排名
  • ROW_NUMBER连续排名,即使相同的值,依旧按照连续数字进行排名

区别如图:

1.2 分组排名

将数据分组后排名,区别如图:

2. 准备数据

创建一张分数表,里面有字段:分数score,课程号course_id和学生号student_id。

执行如下SQL语句,进行导入数据。

java 复制代码
create table score(
  student_id varchar(10),
  course_id varchar(10),
  score decimal(18,1)
);

insert into score values('01' , '01' , 80);
insert into score values('01' , '02' , 90);
insert into score values('01' , '03' , 99);
insert into score values('02' , '01' , 70);
insert into score values('02' , '02' , 60);
insert into score values('02' , '03' , 80);
insert into score values('03' , '01' , 80);
insert into score values('03' , '02' , 80);
insert into score values('03' , '03' , 80);
insert into score values('04' , '01' , 50);
insert into score values('04' , '02' , 30);
insert into score values('04' , '03' , 20);
insert into score values('05' , '01' , 76);
insert into score values('05' , '02' , 87);
insert into score values('06' , '01' , 31);
insert into score values('06' , '03' , 34);
insert into score values('07' , '02' , 89);
insert into score values('07' , '03' , 98);
insert into score values('08' , '02' , 89);
insert into score values('09' , '02' , 89);

查看数据:

3. 不分组排名

3.1 连续排名

  1. 使用ROW_NUMBER实现:

    java 复制代码
    SELECT score,
    ROW_NUMBER() OVER (ORDER BY score DESC) ranking
    FROM score;
  2. 使用变量实现:

    java 复制代码
    SELECT s.score, (@cur_rank := @cur_rank + 1) ranking
    FROM score s, (SELECT @cur_rank := 0) r
    ORDER BY score DESC;

结果如图:

3.2 并列跳跃排名

  1. 使用RANK实现:

    java 复制代码
    SELECT course_id, score,
    RANK() OVER(ORDER BY score DESC)
    FROM score;
  2. 使用变量和IF语句实现:

    java 复制代码
    SELECT s.score,
    @rank_counter := @rank_counter + 1,
    IF(@pre_score = s.score, @cur_rank, @cur_rank := @rank_counter) ranking,
    @pre_score := s.score
    FROM score s, (SELECT @cur_rank :=0, @pre_score := NULL, @rank_counter := 0) r
    ORDER BY s.score DESC;
  3. 使用变量和CASE语句实现:

    java 复制代码
    SELECT s.score,
    @rank_counter := @rank_counter + 1,
    (
      CASE
      WHEN @pre_score = s.score THEN @cur_rank
      WHEN @pre_score := s.score THEN @cur_rank := @rank_counter
      END
    ) ranking
    FROM score s, (SELECT @cur_rank :=0, @pre_score := NULL, @rank_counter := 0) r
    ORDER BY s.score DESC;

结果如图:

3.3 并列连续排名

  1. 使用DENSE_RANK实现:

    java 复制代码
    SELECT course_id, score,
    DENSE_RANK() OVER(ORDER BY score DESC) FROM score;
  2. 使用变量和IF语句实现:

    java 复制代码
    SELECT s.score,
    IF(@pre_score = s.score, @cur_rank, @cur_rank := @cur_rank + 1) ranking,
    @pre_score := s.score
    FROM score s, (SELECT @cur_rank :=0, @pre_score = NULL) r
    ORDER BY s.score DESC;
  3. 使用变量和CASE语句实现:

    java 复制代码
    SELECT s.score,
    (
      CASE
      WHEN @pre_score = s.score THEN @cur_rank
      WHEN @pre_score := s.score THEN @cur_rank := @cur_rank + 1
      END
    ) ranking
    FROM score s, (SELECT @cur_rank :=0, @pre_score = NULL) r
    ORDER BY s.score DESC;

结果如图:

4. 分组排名

4.1 分组连续排名

  1. 使用ROW_NUMBER实现:

    java 复制代码
    SELECT course_id, score,
    ROW_NUMBER() OVER (PARTITION BY course_id ORDER BY score DESC) ranking FROM score;
  2. 使用变量和IF语句实现:

    java 复制代码
    SELECT s.course_id, s.score,
    IF(@pre_course_id = s.course_id, @cur_rank := @cur_rank + 1, @cur_rank := 1) ranking,
    @pre_course_id := s.course_id
    FROM score s, (SELECT @cur_rank := 0, @pre_course_id := NULL) r
    ORDER BY course_id, score DESC;

结果如图:

4.2 分组并列跳跃排名

  1. 使用RANK实现:

    java 复制代码
    SELECT course_id, score,
    RANK() OVER(PARTITION BY course_id ORDER BY score DESC)
    FROM score;
  2. 使用变量和IF语句实现:

    java 复制代码
    SELECT s.course_id, s.score,
    IF(@pre_course_id = s.course_id,
       @rank_counter := @rank_counter + 1,
       @rank_counter := 1) temp1,
    IF(@pre_course_id = s.course_id,
       IF(@pre_score = s.score, @cur_rank, @cur_rank := @rank_counter),
       @cur_rank := 1) ranking,
    @pre_score := s.score temp2,
    @pre_course_id := s.course_id temp3
    FROM score s, (SELECT @cur_rank := 0, @pre_course_id := NULL, @pre_score := NULL, @rank_counter := 1)r
    ORDER BY s.course_id, s.score DESC;

结果如图:

4.3 分组并列连续排名

  1. 使用DENSE_RANK实现:

    java 复制代码
    SELECT course_id, score,
    DENSE_RANK() OVER(PARTITION BY course_id ORDER BY score DESC)
    FROM score;
  2. 使用变量和IF语句实现:

    java 复制代码
    SELECT s.course_id, s.score,
    IF(@pre_course_id = s.course_id,
       IF(@pre_score = s.score, @cur_rank, @cur_rank := @cur_rank + 1),
       @cur_rank := 1) ranking,
    @pre_score := s.score,
    @pre_course_id := s.course_id
    FROM score s, (SELECT @cur_rank :=0, @pre_score = NULL, @pre_course_id := NULL) r
    ORDER BY course_id, score DESC;

    可以将上述的IF条件提取出来:

    java 复制代码
    SELECT s.course_id, s.score,
    IF(@pre_score = s.score, @cur_rank, @cur_rank := @cur_rank + 1) temp1,
    @pre_score := s.score temp2,
    IF(@pre_course_id = s.course_id, @cur_rank, @cur_rank := 1) ranking,
    @pre_course_id := s.course_id
    FROM score s, (SELECT @cur_rank :=0, @pre_score = NULL, @pre_course_id := NULL) r
    ORDER BY course_id, score DESC;

结果如图:

相关推荐
笨鸟先飞,勤能补拙4 小时前
AI 赋能网络安全:技术全景、成熟度评估与实战案例
人工智能·python·安全·web安全·网络安全·sqlite·github
summerkissyou19874 小时前
Android - 摄像头 - hal - 开发教程,例子,常见问题,分析方法,解决方案
android
长和信泰光伏储能4 小时前
京津冀光伏发电:绿色能源的未来之路
python·能源
浦信仿真大讲堂5 小时前
从重复操作到自动化闭环:如何让 CST 与 Python 真正协同起来
python·自动化·cst·仿真软件·达索软件
summerkissyou19875 小时前
Android 16 架构图
android
Gu Gu Study5 小时前
ScoutLoop开放域深度研究引擎(agent的初步设计想法)
人工智能·python
神龙天舞20015 小时前
MySQL 备库为什么会延迟好几个小时
android·数据库·mysql
卷无止境6 小时前
写代码这件事,到底该讲究点什么?
后端·python
卷无止境6 小时前
循环复杂度到底在算什么,Python 代码怎么才能写得让人一看就懂
后端·python
lpfasd1236 小时前
MediaCrawler 项目深度分析
chrome·python·chrome devtools