经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MySQL » 查看文章
MySQL中多种排名实现
来源:cnblogs  作者:程序员Forlan  时间:2023/2/1 16:27:23  对本文有异议
 

一、数据库表结构以及数据

  1. CREATE TABLE `forlan_score` (
  2. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  3. `student_name` varchar(255) DEFAULT NULL COMMENT '学生名称',
  4. `score` int(20) DEFAULT '-1' COMMENT '分数',
  5. `course_name` varchar(255) DEFAULT NULL COMMENT '课程',
  6. PRIMARY KEY (`id`) USING BTREE
  7. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='学生成绩表';
  8. INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (1, '小明', 70, '数学');
  9. INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (2, '小红', 65, '英语');
  10. INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (3, '小林', 100, '数学');
  11. INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (4, '小黄', 100, '语文');
  12. INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (5, '小东', 80, '语文');
  13. INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (6, '小美', 90, '英语');
  14. INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (7, '小伟', 88, '英语');
  15. INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (8, '小小', 100, '数学');

二、实现排名(不分组)

1、不重复,连续

1.1、不同版本实现

1)mysql5.7实现

  • 使用自定义变量(外部sql)
  1. SET @cur_rank := 0;
  2. SELECT
  3. student_name,
  4. score,
  5. @cur_rank := @cur_rank + 1 AS ranking
  6. FROM
  7. forlan_score
  8. ORDER BY
  9. score DESC;
  • 使用自定义变量(内部sql)(推荐)
  1. SELECT
  2. fs.student_name,
  3. fs.score,
  4. ( @cur_rank := @cur_rank + 1 ) AS ranking
  5. FROM
  6. forlan_score fs,
  7. ( SELECT @cur_rank := 0 ) r
  8. ORDER BY
  9. score DESC;

2)mysql8实现

ROW_NUMBER()

  1. SELECT
  2. student_name,
  3. score,
  4. ROW_NUMBER() OVER ( ORDER BY score DESC ) AS ranking
  5. FROM
  6. forlan_score;

1.2、效果

  1. +--------------+-------+---------+
  2. | student_name | score | ranking |
  3. +--------------+-------+---------+
  4. | 小林 | 100 | 1 |
  5. | 小黄 | 100 | 2 |
  6. | 小小 | 100 | 3 |
  7. | 小美 | 90 | 4 |
  8. | 小伟 | 88 | 5 |
  9. | 小东 | 80 | 6 |
  10. | 小明 | 70 | 7 |
  11. | 小红 | 65 | 8 |
  12. +--------------+-------+---------+

2、并列排名,连续

2.1、不同版本实现

1)mysql5.7实现

  • 使用自定义变量 + IF
  1. SELECT
  2. fs.student_name,
  3. fs.score,
  4. IF( @pre_score = fs.score, @cur_rank, @cur_rank := @cur_rank + 1 ) AS ranking,
  5. @pre_score := fs.score
  6. FROM
  7. forlan_score fs,( SELECT @cur_rank := 0, @pre_score := NULL ) r
  8. ORDER BY
  9. fs.score DESC;
  • 使用自定义变量 + CASE WHEN
  1. SELECT
  2. fs.student_name,
  3. fs.score,
  4. (
  5. CASE
  6. WHEN @pre_score = fs.score THEN @cur_rank
  7. WHEN @pre_score := fs.score THEN @cur_rank := @cur_rank + 1
  8. END
  9. ) AS ranking
  10. FROM
  11. forlan_score fs,(SELECT @cur_rank := 0,@pre_score := NULL) r
  12. ORDER BY
  13. fs.score DESC;

2)mysql8实现

DENSE_RANK()

  1. SELECT
  2. student_name,
  3. score,
  4. DENSE_RANK() OVER ( ORDER BY score DESC ) AS ranking
  5. FROM
  6. forlan_score;

2.2、效果

  1. +--------------+-------+---------+
  2. | student_name | score | ranking |
  3. +--------------+-------+---------+
  4. | 小林 | 100 | 1 |
  5. | 小黄 | 100 | 1 |
  6. | 小小 | 100 | 1 |
  7. | 小美 | 90 | 2 |
  8. | 小伟 | 88 | 3 |
  9. | 小东 | 80 | 4 |
  10. | 小明 | 70 | 5 |
  11. | 小红 | 65 | 6 |
  12. +--------------+-------+---------+

3、并列排名,不连续

3.1、不同版本实现

1)mysql5.7实现

  • 使用自定义变量 + IF
  1. SELECT
  2. fs.student_name,
  3. fs.score,
  4. @row_num := @row_num + 1,
  5. IF( @pre_score = fs.score, @cur_rank, @cur_rank := @row_num ) AS ranking,
  6. @pre_score := fs.score
  7. FROM
  8. forlan_score fs,
  9. (SELECT @cur_rank := 0,@pre_score := NULL,@row_num := 0 ) r
  10. ORDER BY
  11. fs.score DESC;
  • 使用自定义变量 + CASE WHEN
  1. SELECT
  2. fs.student_name,
  3. fs.score,
  4. @row_num := @row_num + 1,
  5. ( CASE WHEN @pre_score = fs.score THEN @cur_rank WHEN @pre_score := fs.score THEN @cur_rank := @row_num END ) AS ranking
  6. FROM
  7. forlan_score fs,
  8. ( SELECT @cur_rank := 0, @pre_score := NULL, @row_num := 0 ) r
  9. ORDER BY
  10. fs.score DESC;

2)mysql8实现

RANK()

  1. SELECT
  2. student_name,
  3. score,
  4. RANK() OVER ( ORDER BY score DESC ) AS ranking
  5. FROM
  6. forlan_score;

3.2、效果

  1. +--------------+-------+---------+
  2. | student_name | score | ranking |
  3. +--------------+-------+---------+
  4. | 小林 | 100 | 1 |
  5. | 小黄 | 100 | 1 |
  6. | 小小 | 100 | 1 |
  7. | 小美 | 90 | 4 |
  8. | 小伟 | 88 | 5 |
  9. | 小东 | 80 | 6 |
  10. | 小明 | 70 | 7 |
  11. | 小红 | 65 | 8 |
  12. +--------------+-------+---------+

三、按照课程分组实现排名

1、不重复,连续

1.1、不同版本实现

1)mysql5.7实现

  • 使用自定义变量 + IF
  1. SELECT
  2. fs.student_name,
  3. fs.course_name,
  4. fs.score,
  5. IF(@cur_couse = course_name, @cur_rank := @cur_rank+1, @cur_rank :=1) AS ranking,
  6. @cur_couse := fs.course_name
  7. FROM
  8. forlan_score fs,
  9. ( SELECT @cur_rank := 0, @cur_couse := NULL ) r
  10. ORDER BY
  11. fs.course_name,fs.score DESC;

2)mysql8实现

ROW_NUMBER()

  1. SELECT
  2. student_name,
  3. course_name,
  4. score,
  5. ROW_NUMBER() OVER (PARTITION BY course_name ORDER BY course_name,score DESC) AS ranking
  6. FROM
  7. forlan_score;

1.2、效果

  1. +--------------+-------------+-------+---------+
  2. | student_name | course_name | score | ranking |
  3. +--------------+-------------+-------+---------+
  4. | 小林 | 数学 | 100 | 1 |
  5. | 小小 | 数学 | 100 | 2 |
  6. | 小明 | 数学 | 70 | 3 |
  7. | 小美 | 英语 | 90 | 1 |
  8. | 小伟 | 英语 | 88 | 2 |
  9. | 小红 | 英语 | 65 | 3 |
  10. | 小黄 | 语文 | 100 | 1 |
  11. | 小东 | 语文 | 80 | 2 |
  12. +--------------+-------------+-------+---------+

2、并列排名,连续

2.1、不同版本实现

1)mysql5.7实现

  • 使用自定义变量 + IF
  1. SELECT
  2. fs.student_name,
  3. fs.course_name,
  4. fs.score,
  5. IF(@cur_couse = course_name, IF( @pre_score = fs.score, @cur_rank, @cur_rank := @cur_rank+1 ), @cur_rank :=1) AS ranking,
  6. @pre_score := fs.score,
  7. @cur_couse := fs.course_name
  8. FROM
  9. forlan_score fs,
  10. ( SELECT @cur_rank := 0, @pre_score := NULL, @cur_couse := NULL ) r
  11. ORDER BY
  12. fs.course_name,fs.score DESC;

2)mysql8实现

DENSE_RANK()

  1. SELECT
  2. student_name,
  3. course_name,
  4. score,
  5. DENSE_RANK() OVER (PARTITION BY course_name ORDER BY course_name,score DESC) AS ranking
  6. FROM
  7. forlan_score;

2.2、效果

  1. +--------------+-------------+-------+---------+
  2. | student_name | course_name | score | ranking |
  3. +--------------+-------------+-------+---------+
  4. | 小林 | 数学 | 100 | 1 |
  5. | 小小 | 数学 | 100 | 1 |
  6. | 小明 | 数学 | 70 | 2 |
  7. | 小美 | 英语 | 90 | 1 |
  8. | 小伟 | 英语 | 88 | 2 |
  9. | 小红 | 英语 | 65 | 3 |
  10. | 小黄 | 语文 | 100 | 1 |
  11. | 小东 | 语文 | 80 | 2 |
  12. +--------------+-------------+-------+---------+

3、并列排名,不连续

3.1、不同版本实现

1)mysql5.7实现

  • 使用自定义变量 + IF
  1. SELECT
  2. fs.student_name,
  3. fs.course_name,
  4. fs.score,
  5. IF(@cur_couse = course_name, @row_num := @row_num + 1, @row_num :=1),
  6. IF(@cur_couse = course_name, IF( @pre_score = fs.score, @cur_rank, @cur_rank := @row_num ),@cur_rank :=1) AS ranking,
  7. @pre_score := fs.score,
  8. @cur_couse := fs.course_name
  9. FROM
  10. forlan_score fs,
  11. ( SELECT @cur_rank := 0, @pre_score := NULL, @row_num := 0,@cur_couse := NULL ) r
  12. ORDER BY
  13. fs.course_name,fs.score DESC;

2)mysql8实现

RANK()

  1. SELECT
  2. student_name,
  3. course_name,
  4. score,
  5. RANK() OVER (PARTITION BY course_name ORDER BY course_name,score DESC) AS ranking
  6. FROM
  7. forlan_score;

3.2、效果

  1. +--------------+-------------+-------+---------+
  2. | student_name | course_name | score | ranking |
  3. +--------------+-------------+-------+---------+
  4. | 小林 | 数学 | 100 | 1 |
  5. | 小小 | 数学 | 100 | 1 |
  6. | 小明 | 数学 | 70 | 3 |
  7. | 小美 | 英语 | 90 | 1 |
  8. | 小伟 | 英语 | 88 | 2 |
  9. | 小红 | 英语 | 65 | 3 |
  10. | 小黄 | 语文 | 100 | 1 |
  11. | 小东 | 语文 | 80 | 2 |
  12. +--------------+-------------+-------+---------+

原文链接:https://www.cnblogs.com/huozhonghun/p/17083223.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号