情况说明

查询每门科目的前3名。

对于查询的结果,一般有两种情况。

表所有数据为:

情况1:对于分数相同的人,其后面的人 紧跟着名次排,直到排够名次3,就不再往后取了。

情况2:对于分数相同的人,若当前相同名次的人数大于或等于 3, 则相同分数其后面的人不再参于top3了。

在情况2中 ,为什么”李四 - java“ 这行没有了呢?

可以这样理解,在情况2中相当于使用了名次空缺, 分数相同的人其后面那个人,的名次为 前面的人数+1 , 这里的 ”李四-java“这行,他的名次应当是 5 , 所有top3自然取不到 ”李四-java“这行。

# 查询方法

情况1方法:

# 方法1
SELECT      T1.*
FROM        score_t T1
WHERE       (SELECT COUNT(distinct score) FROM score_t WHERE T1.subject = subject AND T1.score < score) < 3
ORDER BY    subject,score DESC;
-- 思路:
-- 1. 通过子查询的方式 , 查询每条记录中 对应科目比他分数高的
-- 2. 如果比自己还高的 小于3 ,那么自己就是属于top3# 方法2SELECT      T1.*
FROM        score_t T1
LEFT JOIN   (SELECT DISTINCT subject, score FROM score_t) T2
ON          T1.subject = T2.subject
AND         T1.score < T2.score
GROUP BY    name,subject,score
HAVING      COUNT(1) < 3
ORDER BY    subject,score DESC;-- 思路:
-- 1. 找到所有科目对应分数的所有情况 (去重)
-- 2. 和原表关联后, 且比当前 记录 对应科目比自己分数
-- 3. 分组后 找出 次数小于3的
-- 注意: 使用 distinct 去重 和不使用, 区别于并列名次 是否算同一个名额# 方法3
select t.name,t.subject,t.score,t.rank from (select name,subject,score,@r:= if(@psub = subject, if(@psco = score, @r, @r + 1), 1) rank ,@psub:= subject , @psco:= score from score_t, (select @psub:=null, @psco:=null, @r:=0) initorder by subject,score desc
) t where t.rank <=3;
-- 思路:
-- 使用 临时变量, 相同的分数 保持名次不变,否则+1# 方法4
select t1.name,t1.subject,t1.score, count(distinct t2.score)  rank from score_t t1 --
left join score_t t2
on t1.subject = t2.subject and t2.score >= t1.score
group by t1.subject,t1.name,t1.score
having count(distinct t2.score) <= 3
order by subject,score desc ,rank;
-- 和方法2思路一样 , 只是使用 写法不同

情况2方法:

# 方法1:
SELECT      T1.*
FROM        score_t T1
WHERE       (SELECT COUNT(1) FROM score_t WHERE T1.subject = subject AND T1.score < score) < 3
ORDER BY    subject,score DESC;# 方法2    SELECT      T1.*
FROM        score_t T1
LEFT JOIN   (SELECT subject, score FROM score_t) T2
ON          T1.subject = T2.subject
AND         T1.score < T2.scoreGROUP BY  name,subject,score
HAVING      COUNT(1) < 3
ORDER BY    subject,score DESC# 方法3
select t.name,t.subject,t.score,t.rank from (select name,subject,score,@allorder:= if(@psub = subject, @allorder + 1, 1),@r:= if(@psub = subject, if(@psco = score, @r, @allorder), 1) rank , @psub:= subject , @psco:= scorefrom score_t, (select @psub:=null, @psco:=null, @r:=0, @allorder:=0) initorder by subject,score desc
) t where t.rank <=3# 方法4
select t1.name,t1.subject,t1.score  from score_t t1 --
left join score_t t2
on t1.subject = t2.subject and t2.score > t1.score
group by t1.subject,t1.name,t1.score
having count(*) <  3
order by subject,score desc 

情况2和情况 写法都是对应的, 需要注意的是 并列名次,后面的人 是否需要保持名次空缺。那么统计的时候就需要根据情况去重。

数据创建

CREATE TABLE score_t(
name        VARCHAR(10),
subject     VARCHAR(10),
score       INT(10)
);INSERT INTO score_t VALUES
("张三","java",71),
("李四","java",82),
("王五","java",90),
("赵六","java",98),
("孙七","java",90),
("陈八","java",90),
("张三","python",81),
("李四","python",92),
("王五","python",93),
("赵六","python",97),
("刘九","python",93),
("孙七","python",70);

参考链接:

https://blog.csdn.net/weixin_44497013/article/details/107317719

https://leetcode-cn.com/problems/department-top-three-salaries/solution/mysqlzi-ding-yi-bian-liang-shi-xian-fen-lei-pai-xu/

Mysql 分组查询top n(多种方法)相关推荐

  1. Mysql分组查询每组最新的一条数据(三种实现方法)

    MySQL分组查询每组最新的一条数据 前言 注意事项 准备SQL 错误查询 错误原因 方法一 方法二(适用于自增ID和创建时间排序一致) 方法三(适用于自增ID和创建时间排序一致) 总结 MAX()函 ...

  2. mysql 分组查询最新

    mysql分组查询最新 看到网上说到的方法和我写的都一样,也不知道有没有更好的方法,等到解答. SELECT id,group_id from (SELECT id,group_id from tab ...

  3. mysql去重查询的三种方法

    文章目录 前言 一.插入测试数据 二.剔除重复数据方法 1.方法一:使用distinct 2.方法二:使用group by 3.方法三:使用开窗函数 总结 前言 数据库生成环境中经常会遇到表中有重复的 ...

  4. mysql分组查询和分组过滤

    mysql分组查询使用的的关键字是group by,分组过滤使用到的关键字是having.需要先分组查询才能进行分组过滤,个人理解having和where的区别有以下: 1.聚集函数count.sum ...

  5. MySQL分组查询,获取分组后数据

    MySQL分组查询,获取分组后数据 MySQL分组查询,将其它列的数据,合并到一行展示,可以设置去重,设置去重,设置排序,截取指定条数 创建表结构 CREATE TABLE `author_info` ...

  6. MySQL修改root密码的多种方法+给远程登录赋权

    参考http://blog.itpub.net/29578568/viewspace-2149699/ 一.MySQL修改root密码的多种方法 在 Navicat for MySQL 下面直接执行 ...

  7. MySQL分组查询跟聚合函数

    MySQL分组查询跟聚合函数 一.分组查询的语句 GROUP BY { <列名> | <表达式> | <位置> } [ASC | DESC] 这个语句中间{ < ...

  8. mysql分组查询只获取第一条

    mysql分组查询只获取第一条 接到一个需求: 需要获取协议表里所有供应商对应最新的采购员. 由于协议表里供应商的协议会有多个,可能采购员也不是同一个,所以需要做到聚合.筛选才能达到效果. -- 外层 ...

  9. mysql慢查询开启及分析方法

    最近服务维护的公司的DB服务器,总是会出现问题,感觉需要优化一下了,登陆上去,发现慢查询日志都没有开,真是惭愧, 故果断加上慢查询日志,经过分析sql记录,发现问题很多,开发人员很多没有对sql优化, ...

最新文章

  1. gnome硬盘分析_三款基于GUI和终端的实用Linux磁盘扫描工具
  2. “叽里呱啦”说英语,这家公司要用AI增值语言输出能力
  3. 允许root远程登录Solaris
  4. 手机QQ会员H5加速方案——sonic技术内幕
  5. html自定义颜色函数,javascript设置元素背景颜色
  6. eigen3.3.8帮助文档下载 chm_MAXHUB文档v1.10.1-MAXHUB文档电脑版下载
  7. java this关键字的使用_老大:我去,你竟然还不会用 this 关键字
  8. asm扩容流程_Oracle rac asm 扩容
  9. 苹果支持安卓手机以旧换新,华为P30顶配最高才抵扣200元?
  10. linux 错误信息 输出到管道,linux grep通过管道输出到head出现write error: Broken pipe错误...
  11. Hibernate工作流程及与 MyBatis的比较
  12. Java 字符串和时间互相转化 +时间戳
  13. 写歌词的技巧和方法,写歌词的基本要求,歌词创作基本知识及注意事项,创作歌词的要点
  14. C# int与byte之间转换的方法
  15. 交通银行计算机专业招聘笔试题4套,交通银行校园招聘笔试经验分享(试题解析)...
  16. 万字综述:如何打造自动驾驶的数据闭环?
  17. Android热修复技术——QQ空间补丁方案解析(1)
  18. Elasticsearch:Apache spark 大数据集成
  19. JavaScript函数isFinite()
  20. 北冥乘海生:996其实没什么卵用

热门文章

  1. ArcGIS之经纬度表格数据转矢量
  2. 浙大提出神经3D重建新工作!收录图形学顶会SIGGRAPH 2022
  3. 字节跳动2019春招后端开发工程师-笔试题解析
  4. SSM+服装管理系统 毕业设计-附源码080948
  5. Android S关闭定位开关后,定位权限被AppOps限制。
  6. 百家号不收录限流无推荐阅读为零抄袭的解决方法!
  7. 盘点2021款iPad Pro 5个增强功能,与上一代有什么区别?
  8. 股民误将向日葵当成农业股
  9. 安防4G摄像头互联网直播视频流媒体服务器EasyNVR硬件盒子设置固定IP后设备重启无法再次发现设备的问题
  10. AtCoder Grand Contest 021完整题解