MySQL分类排名和分组TOP N实例详解
作者:奔放的程序猿 发布时间:2024-01-24 11:23:16
标签:MySQL,分类,分组
表结构
学生表如下:
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条数据。
SELECT
s1.*
FROM
student s1
LEFT JOIN student s2 ON s1.t_id = s2.t_id
AND s1.score < s2.score
GROUP BY
s1.id
HAVING
COUNT( s2.id ) < 5
ORDER BY
s1.t_id,
s1.score DESC
ps:取前4名时
分析:
1.自身左外连接,得到所有的左边值小于右边值的集合。以t_id=1时举例,24有5个成绩大于他的(74、64、54、44、34),是第6名,34只有4个成绩大于他的,是第5名......74没有大于他的,是第一名。
SELECT
*
FROM
student s1
LEFT 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)
SELECT
s1.*
FROM
student s1
LEFT JOIN student s2 ON s1.t_id = s2.t_id
AND s1.score < s2.score
GROUP BY
s1.id
HAVING
COUNT( s2.id ) < 5
3. 最后根据 t_id 分类,score 倒序排序即可。
题目二:获取每个科目下最后两名学生的成绩平均值
取最后两名成绩
SELECT
s1.*
FROM
student s1
LEFT JOIN student s2 ON s1.t_id = s2.t_id
AND s1.score > s2.score
GROUP BY
s1.id
HAVING
COUNT( s1.id )< 2
ORDER BY
s1.t_id,
s1.score
并列存在情况下可能导致筛选出的同一t_id 下结果条数大于2条,但题目要求是取最后两名的平均值,多条平均后还是本身,故不必再对其处理,可以满足题目要求。
分组求平均值:
SELECT
t_id,AVG(score)
FROM
(
SELECT
s1.*
FROM
student s1
LEFT JOIN student s2 ON s1.t_id = s2.t_id
AND s1.score > s2.score
GROUP BY
s1.id
HAVING
COUNT( s1.id )< 2
ORDER BY
s1.t_id,
s1.score
) tt
GROUP BY
t_id
结果:
分析:
1. 查询出所有t1.score>t2.score 的记录
SELECT
s1.*,s2.*
FROM
student s1
LEFT 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
(
SELECT
s1.*,
@rownum := @rownum + 1 AS num_tmp,
@incrnum :=
CASE
WHEN @rowtotal = s1.score THEN
@incrnum
WHEN @rowtotal := s1.score THEN
@rownum
END AS rownum
FROM
student s1
LEFT 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 BY
s1.id
ORDER BY
s1.t_id,
s1.score DESC
) tt
GROUP BY
t_id,
score,
rownum
HAVING
COUNT( rownum )< 5
分析:
1.引入辅助参数
SELECT
s1.*,
@rownum := @rownum + 1 AS num_tmp,
@incrnum :=
CASE
WHEN @rowtotal = s1.score THEN
@incrnum
WHEN @rowtotal := s1.score THEN
@rownum
END AS rownum
FROM
student s1
LEFT 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,分组排序
SELECT
s1.*,
@rownum := @rownum + 1 AS num_tmp,
@incrnum :=
CASE
WHEN @rowtotal = s1.score THEN
@incrnum
WHEN @rowtotal := s1.score THEN
@rownum
END AS rownum
FROM
student s1
LEFT 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 BY
s1.id
ORDER BY
s1.t_id,
s1.score DESC
3.GROUP BY t_id, score, rownum 然后 HAVING 取前5条不重复的
来源:https://blog.csdn.net/Dlgdlgd/article/details/122129327


猜你喜欢
- 需求背景一个统计接口,前端需要返回两个数组,一个是0-23的小时计数,一个是各小时对应的统计数。思路 直接使用group by查询要统计的表
- 安装jieba库教程jieba库是一款优秀的 Python 第三方中文分词库,jieba 支持三种分词模式:精确模式、全模式和搜索引擎模式,
- mysql_query("set autocommit=0"); $list_one = $db->fetch_f
- GO类型转换及与C的类型转换类型转换语法dst := float32(src)示例var num int = 520f32 := float
- 打开php.ini,首先找到;;;;;;;;;;;;;;;;; file uploads ;;;;;;;;;;;;;;;;;区域,有影响文件
- 目录概述语法一、创建和初始化切片make字面量二、使用切片赋值和切片切片增长遍历切片总结总示例示例一 两个slice是否相等示例
- 在图片处理中,霍夫变换主要是用来检测图片中的几何形状,包括直线、圆、椭圆等。在skimage中,霍夫变换是放在tranform模块内,本篇主
- 1、使用函数shutil.make_archive()创建归档文件,并返回归档后的名称。import shutilpath_1 = r
- ElementUI是饿了么推出的一套基于vue2.x的一个ui框架。官方文档也很详细,这里做一个element-ui日期插件的补充。官方文档
- 常规通过迭代或set方法,都无法保证去重后的顺序问题如下,我们可以通过列表的索引功能,对set结果进行序列化old_list=["
- 前言MySQL提供了众多功能强大、方便易用的函数。使用这些函数可以极大地提高用户对数据库的管理效率。MySQL中的函数包括数学函数、字符串函
- QQ通过返回不同的图片,来表示在线或离线,图标也随之变换,既然图片不同,那么,返回的HTTP头信息中的Content-Length 也一定不
- 前言在对DataFrame数据进行处理时,存在需要对数据内容进行遍历的场景。因此记录一下按照行,列遍历的几种方式。一、按行遍历1. 使用lo
- 本文实例讲述了php获取给定日期相差天数的方法。分享给大家供大家参考,具体如下:方法一:<?phpfunction count_day
- 一、SQLalchemy简介SQLAlchemy是一个开源的SQL工具包,基本Python编程语言的MIT许可证而发布的对象关系映射器。SQ
- 前言本文主要分享一个python代码,可以将多个视频中的音频转化为相同采样率的视频。对视频格式的校验没有做,也不是很关键。环境依赖ffmpe
- class torch.nn.Sequential(* args)一个时序容器。Modules 会以他们传入的顺序被添加到容器中。当然,也可
- SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。在很多嵌入式产品中使用了它,它占用资源非
- 这篇文章主要介绍了python 哈希表实现简单python字典代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学
- 当然有其它工具可以做这件事,但如果客户不允许你在服务器乱装东西时这个脚本就会有用了。 DECLARE @tbImportTables tab