MySQL中多种排名实现
一、数据库表结构以及数据
CREATE TABLE `forlan_score` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`student_name` varchar(255) DEFAULT NULL COMMENT '学生名称',
`score` int(20) DEFAULT '-1' COMMENT '分数',
`course_name` varchar(255) DEFAULT NULL COMMENT '课程',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='学生成绩表';
INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (1, '小明', 70, '数学');
INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (2, '小红', 65, '英语');
INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (3, '小林', 100, '数学');
INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (4, '小黄', 100, '语文');
INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (5, '小东', 80, '语文');
INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (6, '小美', 90, '英语');
INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (7, '小伟', 88, '英语');
INSERT INTO `test`.`forlan_score` (`id`, `student_name`, `score`, `course_name`) VALUES (8, '小小', 100, '数学');
二、实现排名(不分组)
1、不重复,连续
1.1、不同版本实现
1)mysql5.7实现
- 使用自定义变量(外部sql)
SET @cur_rank := 0;
SELECT
student_name,
score,
@cur_rank := @cur_rank + 1 AS ranking
FROM
forlan_score
ORDER BY
score DESC;
- 使用自定义变量(内部sql)(推荐)
SELECT
fs.student_name,
fs.score,
( @cur_rank := @cur_rank + 1 ) AS ranking
FROM
forlan_score fs,
( SELECT @cur_rank := 0 ) r
ORDER BY
score DESC;
2)mysql8实现
ROW_NUMBER()
SELECT
student_name,
score,
ROW_NUMBER() OVER ( ORDER BY score DESC ) AS ranking
FROM
forlan_score;
1.2、效果
+--------------+-------+---------+
| student_name | score | ranking |
+--------------+-------+---------+
| 小林 | 100 | 1 |
| 小黄 | 100 | 2 |
| 小小 | 100 | 3 |
| 小美 | 90 | 4 |
| 小伟 | 88 | 5 |
| 小东 | 80 | 6 |
| 小明 | 70 | 7 |
| 小红 | 65 | 8 |
+--------------+-------+---------+
2、并列排名,连续
2.1、不同版本实现
1)mysql5.7实现
- 使用自定义变量 + IF
SELECT
fs.student_name,
fs.score,
IF( @pre_score = fs.score, @cur_rank, @cur_rank := @cur_rank + 1 ) AS ranking,
@pre_score := fs.score
FROM
forlan_score fs,( SELECT @cur_rank := 0, @pre_score := NULL ) r
ORDER BY
fs.score DESC;
- 使用自定义变量 + CASE WHEN
SELECT
fs.student_name,
fs.score,
(
CASE
WHEN @pre_score = fs.score THEN @cur_rank
WHEN @pre_score := fs.score THEN @cur_rank := @cur_rank + 1
END
) AS ranking
FROM
forlan_score fs,(SELECT @cur_rank := 0,@pre_score := NULL) r
ORDER BY
fs.score DESC;
2)mysql8实现
DENSE_RANK()
SELECT
student_name,
score,
DENSE_RANK() OVER ( ORDER BY score DESC ) AS ranking
FROM
forlan_score;
2.2、效果
+--------------+-------+---------+
| student_name | score | ranking |
+--------------+-------+---------+
| 小林 | 100 | 1 |
| 小黄 | 100 | 1 |
| 小小 | 100 | 1 |
| 小美 | 90 | 2 |
| 小伟 | 88 | 3 |
| 小东 | 80 | 4 |
| 小明 | 70 | 5 |
| 小红 | 65 | 6 |
+--------------+-------+---------+
3、并列排名,不连续
3.1、不同版本实现
1)mysql5.7实现
- 使用自定义变量 + IF
SELECT
fs.student_name,
fs.score,
@row_num := @row_num + 1,
IF( @pre_score = fs.score, @cur_rank, @cur_rank := @row_num ) AS ranking,
@pre_score := fs.score
FROM
forlan_score fs,
(SELECT @cur_rank := 0,@pre_score := NULL,@row_num := 0 ) r
ORDER BY
fs.score DESC;
- 使用自定义变量 + CASE WHEN
SELECT
fs.student_name,
fs.score,
@row_num := @row_num + 1,
( CASE WHEN @pre_score = fs.score THEN @cur_rank WHEN @pre_score := fs.score THEN @cur_rank := @row_num END ) AS ranking
FROM
forlan_score fs,
( SELECT @cur_rank := 0, @pre_score := NULL, @row_num := 0 ) r
ORDER BY
fs.score DESC;
2)mysql8实现
RANK()
SELECT
student_name,
score,
RANK() OVER ( ORDER BY score DESC ) AS ranking
FROM
forlan_score;
3.2、效果
+--------------+-------+---------+
| student_name | score | ranking |
+--------------+-------+---------+
| 小林 | 100 | 1 |
| 小黄 | 100 | 1 |
| 小小 | 100 | 1 |
| 小美 | 90 | 4 |
| 小伟 | 88 | 5 |
| 小东 | 80 | 6 |
| 小明 | 70 | 7 |
| 小红 | 65 | 8 |
+--------------+-------+---------+
三、按照课程分组实现排名
1、不重复,连续
1.1、不同版本实现
1)mysql5.7实现
- 使用自定义变量 + IF
SELECT
fs.student_name,
fs.course_name,
fs.score,
IF(@cur_couse = course_name, @cur_rank := @cur_rank+1, @cur_rank :=1) AS ranking,
@cur_couse := fs.course_name
FROM
forlan_score fs,
( SELECT @cur_rank := 0, @cur_couse := NULL ) r
ORDER BY
fs.course_name,fs.score DESC;
2)mysql8实现
ROW_NUMBER()
SELECT
student_name,
course_name,
score,
ROW_NUMBER() OVER (PARTITION BY course_name ORDER BY course_name,score DESC) AS ranking
FROM
forlan_score;
1.2、效果
+--------------+-------------+-------+---------+
| student_name | course_name | score | ranking |
+--------------+-------------+-------+---------+
| 小林 | 数学 | 100 | 1 |
| 小小 | 数学 | 100 | 2 |
| 小明 | 数学 | 70 | 3 |
| 小美 | 英语 | 90 | 1 |
| 小伟 | 英语 | 88 | 2 |
| 小红 | 英语 | 65 | 3 |
| 小黄 | 语文 | 100 | 1 |
| 小东 | 语文 | 80 | 2 |
+--------------+-------------+-------+---------+
2、并列排名,连续
2.1、不同版本实现
1)mysql5.7实现
- 使用自定义变量 + IF
SELECT
fs.student_name,
fs.course_name,
fs.score,
IF(@cur_couse = course_name, IF( @pre_score = fs.score, @cur_rank, @cur_rank := @cur_rank+1 ), @cur_rank :=1) AS ranking,
@pre_score := fs.score,
@cur_couse := fs.course_name
FROM
forlan_score fs,
( SELECT @cur_rank := 0, @pre_score := NULL, @cur_couse := NULL ) r
ORDER BY
fs.course_name,fs.score DESC;
2)mysql8实现
DENSE_RANK()
SELECT
student_name,
course_name,
score,
DENSE_RANK() OVER (PARTITION BY course_name ORDER BY course_name,score DESC) AS ranking
FROM
forlan_score;
2.2、效果
+--------------+-------------+-------+---------+
| student_name | course_name | score | ranking |
+--------------+-------------+-------+---------+
| 小林 | 数学 | 100 | 1 |
| 小小 | 数学 | 100 | 1 |
| 小明 | 数学 | 70 | 2 |
| 小美 | 英语 | 90 | 1 |
| 小伟 | 英语 | 88 | 2 |
| 小红 | 英语 | 65 | 3 |
| 小黄 | 语文 | 100 | 1 |
| 小东 | 语文 | 80 | 2 |
+--------------+-------------+-------+---------+
3、并列排名,不连续
3.1、不同版本实现
1)mysql5.7实现
- 使用自定义变量 + IF
SELECT
fs.student_name,
fs.course_name,
fs.score,
IF(@cur_couse = course_name, @row_num := @row_num + 1, @row_num :=1),
IF(@cur_couse = course_name, IF( @pre_score = fs.score, @cur_rank, @cur_rank := @row_num ),@cur_rank :=1) AS ranking,
@pre_score := fs.score,
@cur_couse := fs.course_name
FROM
forlan_score fs,
( SELECT @cur_rank := 0, @pre_score := NULL, @row_num := 0,@cur_couse := NULL ) r
ORDER BY
fs.course_name,fs.score DESC;
2)mysql8实现
RANK()
SELECT
student_name,
course_name,
score,
RANK() OVER (PARTITION BY course_name ORDER BY course_name,score DESC) AS ranking
FROM
forlan_score;
3.2、效果
+--------------+-------------+-------+---------+
| student_name | course_name | score | ranking |
+--------------+-------------+-------+---------+
| 小林 | 数学 | 100 | 1 |
| 小小 | 数学 | 100 | 1 |
| 小明 | 数学 | 70 | 3 |
| 小美 | 英语 | 90 | 1 |
| 小伟 | 英语 | 88 | 2 |
| 小红 | 英语 | 65 | 3 |
| 小黄 | 语文 | 100 | 1 |
| 小东 | 语文 | 80 | 2 |
+--------------+-------------+-------+---------+
MySQL中多种排名实现的更多相关文章
- 小白养成记——MySQL中的排名函数
1.ROW_NUMBER() 函数 依次排序,没有并列名次.如 SELECT st.ID '学号', st.`NAME` '姓名', sc.SCORE '成绩', ROW_NUMBER() OVER( ...
- 在MySQL中实现Rank高级排名函数【转】
MySQL中没有Rank排名函数,当我们需要查询排名时,只能使用MySQL数据库中的基本查询语句来查询普通排名.尽管如此,可不要小瞧基础而简单的查询语句,我们可以利用其来达到Rank函数一样的高级排名 ...
- 在MySQL中实现Rank高级排名函数
MySQL中没有Rank排名函数,当我们需要查询排名时,只能使用MySQL数据库中的基本查询语句来查询普通排名.尽管如此,可不要小瞧基础而简单的查询语句,我们可以利用其来达到Rank函数一样的高级排名 ...
- MySQL中的information_schema数据库表说明
MySQL 中的 information_schema 数据库 版权声明:https://blog.csdn.net/kikajack/article/details/80065753 1. 概述 ...
- 【转】MySQL中information_schema是什么
大家在安装或使用MYSQL时,会发现除了自己安装的数据库以外,还有一个information_schema数据库. information_schema数据库是做什么用的呢,使用WordPress博客 ...
- 【MySQL】漫谈MySQL中的事务及其实现
最近一直在做订单类的项目,使用了事务.我们的数据库选用的是MySQL,存储引擎选用innoDB,innoDB对事务有着良好的支持.这篇文章我们一起来扒一扒事务相关的知识. 为什么要有事务? 事务广泛的 ...
- [数据库事务与锁]详解五: MySQL中的行级锁,表级锁,页级锁
注明: 本文转载自http://www.hollischuang.com/archives/914 在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的 ...
- mysql中,主键与普通索引
一.什么是索引?索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录.表里 ...
- [原创]java WEB学习笔记78:Hibernate学习之路---session概述,session缓存(hibernate 一级缓存),数据库的隔离级别,在 MySql 中设置隔离级别,在 Hibernate 中设置隔离级别
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- 漫谈MySql中的事务
最近一直在做订单类的项目,使用了事务.我们的数据库选用的是MySql,存储引擎选用innoDB,innoDB对事务有着良好的支持.这篇文章我们一起来扒一扒事务相关的知识. 为什么要有事务? 事务广泛的 ...
随机推荐
- 在FreeSQL中实现「触发器」和软删除功能
前言 最近做新项目,技术栈 AspNetCore + FreeSQL 这个ORM真的好用,文档也很完善,这里记录一下两个有关「触发器」的功能实现 修改实体时记录更新时间 模型代码 我的模型都是基于这个 ...
- 洛谷 P3201 梦幻布丁 题解
(这篇题解可能没什么营养,主要是记录一下我用map乱搞启发式合并的神奇做法) 首先我们知道,我们肯定要用一堆集合维护每一种数当前的位置,并支持合并和数连续出现的段数两种操作 我发现这个东西并不好搞,但 ...
- django-environ学习
官方说明:https://django-environ.readthedocs.io/en/latest/index.html install pip install django-environ q ...
- TASK 总结
信相连知识 1.python操作EXCEL 库:xlwings. 基本操作:打开.读写.关闭. 2.python操作问题库 库:JIRA 基本操作:提交问题 3.网页信息在网址不变时的获取 库:req ...
- Java继承Frame画一个窗口显示图片
将图片显示到窗口上. 在工程目录下准备好图片5.png 运行代码: import javax.imageio.ImageIO; import java.awt.*; import java.awt.e ...
- 《吐血整理》高级系列教程-吃透Fiddler抓包教程(34)-Fiddler如何抓取微信小程序的包-上篇
1.简介 有些小伙伴或者是童鞋们说小程序抓不到包,该怎么办了???其实苹果手机如果按照宏哥前边的抓取APP包的设置方式设置好了,应该可以轻松就抓到包了.那么安卓手机小程序就比较困难,不是那么友好了.所 ...
- CSP-J2022 题解报告
\(CSP-J2022\) 题解报告 \(T1\) 乘方: 发现 \(2^{32}>10^9\),所以这个题只需要特判 \(a=1\) 的情况为 \(1\),其他直接枚举再判断即可. Code: ...
- 2022春每日一题:Day 36
题目:[JLOI2013]删除物品 直接做显然比较复杂,这个题是说对顶栈,但是可以把两个栈拼在一起,记录一下栈顶的下标,然后这样这题就可以转化为线性上的操作查询了,用树状数组简单维护一下就ok了(某个 ...
- Git+Github协作开发流程
采用合作开发者的方式进行协作开发,下面以zlcook和zlserver合作开发iqas-ios-record项目为例进行讲解,zlcook为项目创建者,zlserver为项目参与者.协作开发步骤如下: ...
- Java-ArrayList应用
存储随机数字 ArrayListRandom.java package cn.day04; import java.util.ArrayList; import java.util.Random; p ...