MySQL 分类排名(并列、不并列),分组TOP N,ROW_NUMBER()函数
目录
表结构
题目一:获取每个科目下前五成绩排名(允许并列)
分析:
题目二:获取每个科目下最后两名学生的成绩平均值
分析:
题目三:获取每个科目下前五成绩排名(不允许并列)
分析:
ROW_NUMBER()函数版
参考资料:
表结构
学生表如下:
CREATE TABLE `t_student` (`id` int NOT NULL AUTO_INCREMENT,`t_id` int DEFAULT NULL COMMENT '学科id',`score` int DEFAULT NULL COMMENT '分数',PRIMARY KEY (`id`)
);
数据如下:
题目一:获取每个科目下前五成绩排名(允许并列)
允许并列情况可能存在如4、5名成绩并列情况,会导致取前4名得出5条数据,取前5名也是5条数据。
SELECTs1.*
FROMstudent s1LEFT JOIN student s2 ON s1.t_id = s2.t_id AND s1.score < s2.score
GROUP BYs1.id
HAVINGCOUNT( s2.id ) < 5
ORDER BYs1.t_id,s1.score DESC
ps:取前4名时
分析:
1.自身左外连接,得到所有的左边值小于右边值的集合。以t_id=1时举例,24有5个成绩大于他的(74、64、54、44、34),是第6名,34只有4个成绩大于他的,是第5名......74没有大于他的,是第一名。
SELECT*
FROMstudent s1LEFT JOIN student s2 ON s1.t_id = s2.t_id AND s1.score < s2.score
2. 把总结的规律转换成SQL表示出来,就是group by 每个student 的 id(s1.id),Having统计这个id下面有多少个比他大的值(s2.id)
SELECTs1.*
FROMstudent s1LEFT JOIN student s2 ON s1.t_id = s2.t_id AND s1.score < s2.score
GROUP BYs1.id
HAVINGCOUNT( s2.id ) < 5
3. 最后根据 t_id 分类,score 倒序排序即可。
题目二:获取每个科目下最后两名学生的成绩平均值
取最后两名成绩
SELECTs1.*
FROMstudent s1LEFT JOIN student s2 ON s1.t_id = s2.t_id AND s1.score > s2.score
GROUP BYs1.id
HAVINGCOUNT( s1.id )< 2
ORDER BYs1.t_id,s1.score
并列存在情况下可能导致筛选出的同一t_id 下结果条数大于2条,但题目要求是取最后两名的平均值,多条平均后还是本身,故不必再对其处理,可以满足题目要求。
分组求平均值:
SELECTt_id,AVG(score)
FROM(SELECTs1.*FROMstudent s1LEFT JOIN student s2 ON s1.t_id = s2.t_id AND s1.score > s2.scoreGROUP BYs1.id HAVINGCOUNT( s1.id )< 2 ORDER BYs1.t_id,s1.score ) tt
GROUP BYt_id
结果:
分析:
1. 查询出所有t1.score>t2.score 的记录
SELECTs1.*,s2.*FROMstudent s1LEFT JOIN student s2 ON s1.t_id = s2.t_id AND s1.score > s2.score
2. group by s.id 去重,having 计数取2条
3. group by t_id 分别取各自学科的然后avg取均值
题目三:获取每个科目下前五成绩排名(不允许并列)
SELECT*
FROM(SELECTs1.*,@rownum := @rownum + 1 AS num_tmp,@incrnum :=CASEWHEN @rowtotal = s1.score THEN@incrnum WHEN @rowtotal := s1.score THEN@rownum END AS rownum FROMstudent s1LEFT JOIN student s2 ON s1.t_id = s2.t_id AND s1.score > s2.score,( SELECT @rownum := 0, @rowtotal := NULL, @incrnum := 0 ) AS it GROUP BYs1.id ORDER BYs1.t_id,s1.score DESC ) tt
GROUP BYt_id,score,rownum
HAVINGCOUNT( rownum )< 5
分析:
1.引入辅助参数
SELECTs1.*,@rownum := @rownum + 1 AS num_tmp,@incrnum :=
CASEWHEN @rowtotal = s1.score THEN@incrnum WHEN @rowtotal := s1.score THEN@rownum END AS rownum
FROMstudent s1LEFT JOIN student s2 ON s1.t_id = s2.t_id AND s1.score > s2.score,( SELECT @rownum := 0, @rowtotal := NULL, @incrnum := 0 ) AS it
2.去除重复s1.id,分组排序
SELECTs1.*,@rownum := @rownum + 1 AS num_tmp,@incrnum :=CASEWHEN @rowtotal = s1.score THEN@incrnum WHEN @rowtotal := s1.score THEN@rownum END AS rownum FROMstudent s1LEFT JOIN student s2 ON s1.t_id = s2.t_id AND s1.score > s2.score,( SELECT @rownum := 0, @rowtotal := NULL, @incrnum := 0 ) AS it GROUP BYs1.id ORDER BYs1.t_id,s1.score DESC
3.GROUP BY t_id, score, rownum 然后 HAVING 取前5条不重复的
ROW_NUMBER()函数版
必要条件:MySQL版本 8.0+
row_number() OVER ([PARTITION BY COL1] ORDER BY COL2)
表示根据COL1分组,在分组内部根据 COL2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内连续的唯一的)。
select * from (SELECT*,ROW_NUMBER() OVER(PARTITION BY t_id ORDER BY score DESC) top
FROMstudent
)t where top<=5
参考资料:
Mysql - 获取每个分类下面前几条数据
mysql mysql SELECT 自增数显示
mysql 每个分类前十名_一文解决所有MySQL分类排名问题
mysql:名次排名 (并列与不并列)
查询每个班成绩排名前三的学生信息
mysql mysql SELECT 自增数显示
MySQL 实现分组 TopN 问题
MySQL 分类排名(并列、不并列),分组TOP N,ROW_NUMBER()函数相关推荐
- mysql 每个分类前十名_一文解决所有MySQL分类排名问题
导读 对数据库中的记录依据某个字段进行排序是一种常见需求,虽然简单的Order by可以胜任,但如果想要输出具体的排名却难以直接实现.如果再考虑重复排名或者分类排名,那么情况就更为复杂. 本文介绍4种 ...
- mysql怎么查询排第几名并列_MySQL并列排名和顺序排名查询
准备.创建一张叫scores的表,内容如下.因为测试排名,所以就用最简单的结构.idscore199 280 387 460 580 699 需求.获取分数排名,要求并列排名.如果两个分数相同,则两个 ...
- mysql怎么做排名并列_MySQL实现排名并查询指定用户排名功能,并列排名功能
MySQL实现排名并查询指定用户排名功能,并列排名功能 表结构: CREATE TABLE test.testsort ( id int(11) NOT NULL AUTO_INCREMENT, ui ...
- mysql并列查询_MYSQL实现排名及查询指定用户排名功能(并列排名功能)实例代码...
前言 本文主要介绍了关于mysql实现排名及查询指定用户排名功能(并列排名功能)的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧 表结构: create table test ...
- mysql作排名,MYSQL实现排名及查询指定用户排名功能(并列排名功能)实例代码...
前言 本文主要介绍了关于MYSQL实现排名及查询指定用户排名功能(并列排名功能)的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧 表结构: CREATE TABLE test ...
- MySQL 实现排名(分组排名)
在MYSQL的最新版本MYSQL8已经支持了排名函数RANK,DENSE_RANK和ROW_NUMBER.但是在5.*版本中还不支持这些函数,只能自己实现.实现方法主要用到了条件判断语句(CASE W ...
- MySQL实现排名、分组筛选、TopN问题
之前在学习SQL时刷过一遍LeetCode上的SQL题,不过只做一遍效果并不是很好,很快也忘记了具体的解题思路.在这里将对其中的:Q176(第二高薪水) . Q177(第N高薪水) . Q178(分数 ...
- n个人排名,允许并列名次,共有多少种排名结果?
n个人排名,允许并列名次,共有多少种排名结果? 经典问题了,可以考虑递推: 假设n个人,排出了m个名次,有f(n,m)种结果(1<=m<=n) 当m=1 f(n,m)=1 当n<m ...
- 编程:假设有n个人进行排名,允许并列排名,名次并列人的不同顺序算一种,总共有多少种排名?
疯狂游戏笔试一道有趣的编程题:排名问题 题目描述 解题思路 代码 题目描述 假设有n个人进行排名,允许并列排名,名次并列人的不同顺序算一种,总共有多少种排名? 例:n=2,输出3,有:a>b,a ...
最新文章
- 用ASP.NET上传图片并生成带版权信息的缩略图
- 【割边缩点】解题报告:POJ - 3694 - Network(Tarjan割边缩点 + LCA + 并查集优化)
- python 入门笔记
- python提取个十百千位数字_实现人脸识别、人脸68个特征点提取,或许这个 Python 库能帮到你!...
- linux-free命令
- undefined reference to `pthread_create‘(linux下Clion使用thread报错)
- Map.putAll方法——追加另一个Map对象到当前Map集合
- dgl._ffi.base.DGLError: Cannot assign node feature “n_feat“ on device cuda:0 to a graph on device
- c# 注册了Ctrl+空格为热键,捕获后发送Ctrl+Shift
- 王思聪吃热狗火了,程序员开发各种恶搞小程序!王校长:我不要脸的啊
- Ali-tomcat之HSF框架Demo启动报错HSFServiceAddressNotFoundException
- 【安卓手机驱动无法安装则无法连接电脑,终极100%解决方法】ADB interfacm与 Andriod安装出现黄色感叹号
- 连接校园网后登不上图书馆里的SCI等网站问题
- 460. LFU缓存
- (OpenCV+Python)--目标跟踪,卡尔曼滤波+鼠标轨迹跟踪
- 搜索引擎推广公司引擎推广方法及技巧
- Ubuntu18.04键盘错乱问题
- 【urllib的使用(下)】
- 智慧交管可视化决策系统
- 非接环境(PPSE)和接触环境(PSE)的FCI有什么区别