获取分组后的TOP 1和TOP N记录
MySQL获取分组后的TOP 1和TOP N记录
有时会碰到一些需求,查询分组后的最大值,最小值所在的整行记录或者分组后的top n行的记录,在一些别的数据库可能有窗口函数可以方面的查出来,但是MySQL没有这些函数,没有直接的方法可以查出来,可通过以下的方法来查询。
准备工作
测试表结构如下:

root:test> show create table test1\G
*************************** 1. row ***************************
Table: test1
Create Table: CREATE TABLE `test1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`course` varchar(20) DEFAULT NULL,
`score` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

插入数据:

insert into test1(name,course,score)
values
('张三','语文',80),
('李四','语文',90),
('王五','语文',93),
('张三','数学',77),
('李四','数学',68),
('王五','数学',99),
('张三','英语',90),
('李四','英语',50),
('王五','英语',89);

查看结果:

root:test> select * from test1;
+----+--------+--------+-------+
| id | name | course | score |
+----+--------+--------+-------+
| 1 | 张三 | 语文 | 80 |
| 2 | 李四 | 语文 | 90 |
| 3 | 王五 | 语文 | 93 |
| 4 | 张三 | 数学 | 77 |
| 5 | 李四 | 数学 | 68 |
| 6 | 王五 | 数学 | 99 |
| 7 | 张三 | 英语 | 90 |
| 8 | 李四 | 英语 | 50 |
| 9 | 王五 | 英语 | 89 |
+----+--------+--------+-------+

TOP 1
查询每门课程分数最高的学生以及成绩
1、使用自连接【推荐】

root:test> select a.name,a.course,a.score from
-> test1 a
-> join (select course,max(score) score from test1 group by course) b
-> on a.course=b.course and a.score=b.score;
+--------+--------+-------+
| name | course | score |
+--------+--------+-------+
| 王五 | 语文 | 93 |
| 王五 | 数学 | 99 |
| 张三 | 英语 | 90 |
+--------+--------+-------+
3 rows in set (0.00 sec)

2、使用相关子查询

root:test> select name,course,score from test1 a
-> where score=(select max(score) from test1 where a.course=test1.course);
+--------+--------+-------+
| name | course | score |
+--------+--------+-------+
| 王五 | 语文 | 93 |
| 王五 | 数学 | 99 |
| 张三 | 英语 | 90 |
+--------+--------+-------+
3 rows in set (0.00 sec)

或者

root:test> select name,course,score from test1 a
-> where not exists(select 1 from test1 where a.course=test1.course and a.score < test1.score);
+--------+--------+-------+
| name | course | score |
+--------+--------+-------+
| 王五 | 语文 | 93 |
| 王五 | 数学 | 99 |
| 张三 | 英语 | 90 |
+--------+--------+-------+
3 rows in set (0.00 sec)

TOP N
N>=1
查询每门课程前两名的学生以及成绩
1、使用union all
如果结果集比较小,可以用程序查询单个分组结果后拼凑,也可以使用union all

root:test> (select name,course,score from test1 where course='语文' order by score desc limit 2)
-> union all
-> (select name,course,score from test1 where course='数学' order by score desc limit 2)
-> union all
-> (select name,course,score from test1 where course='英语' order by score desc limit 2);
+--------+--------+-------+
| name | course | score |
+--------+--------+-------+
| 王五 | 语文 | 93 |
| 李四 | 语文 | 90 |
| 王五 | 数学 | 99 |
| 张三 | 数学 | 77 |
| 张三 | 英语 | 90 |
| 王五 | 英语 | 89 |
+--------+--------+-------+
6 rows in set (0.01 sec)

2、自身左连接

root:test> select a.name,a.course,a.score
-> from test1 a left join test1 b on a.course=b.course and a.score<b.score
-> group by a.name,a.course,a.score
-> having count(b.id)<2
-> order by a.course,a.score desc;
+--------+--------+-------+
| name | course | score |
+--------+--------+-------+
| 王五 | 数学 | 99 |
| 张三 | 数学 | 77 |
| 张三 | 英语 | 90 |
| 王五 | 英语 | 89 |
| 王五 | 语文 | 93 |
| 李四 | 语文 | 90 |
+--------+--------+-------+
6 rows in set (0.00 sec)

3、相关子查询

root:test> select *
-> from test1 a
-> where 2>(select count(*) from test1 where course=a.course and score>a.score)
-> order by a.course,a.score desc;
+----+--------+--------+-------+
| id | name | course | score |
+----+--------+--------+-------+
| 6 | 王五 | 数学 | 99 |
| 4 | 张三 | 数学 | 77 |
| 7 | 张三 | 英语 | 90 |
| 9 | 王五 | 英语 | 89 |
| 3 | 王五 | 语文 | 93 |
| 2 | 李四 | 语文 | 90 |
+----+--------+--------+-------+
6 rows in set (0.01 sec)

4、使用用户变量

root:test> set @num := 0, @course := '';
Query OK, 0 rows affected (0.00 sec) root:test>
root:test> select name, course, score
-> from (
-> select name, course, score,
-> @num := if(@course = course, @num + 1, 1) as row_number,
-> @course := course as dummy
-> from test1
-> order by course, score desc
-> ) as x where x.row_number <= 2;
+--------+--------+-------+
| name | course | score |
+--------+--------+-------+
| 王五 | 数学 | 99 |
| 张三 | 数学 | 77 |
| 张三 | 英语 | 90 |
| 王五 | 英语 | 89 |
| 王五 | 语文 | 93 |
| 李四 | 语文 | 90 |
+--------+--------+-------+
6 rows in set (0.00 sec) ORACLE 可以使用排序函数
select *
from (select row_number() over(partition by course order by score desc) rn,
t.*
from TEST1 t) a
where a.rn <= 2

获取分组后的TOP 1和TOP N记录的更多相关文章
- SQL获取分组后取某字段最大一条记录(求每个类别中最大的值的列表)
获取分组后取某字段最大一条记录 方法一:(效率最高) select * from test as a where typeindex = (select max(b.typeindex) from t ...
- MySQL获取分组后的TOP 1和TOP N记录-转
有时会碰到一些需求,查询分组后的最大值,最小值所在的整行记录或者分组后的top n行的记录,在一些别的数据库可能有窗口函数可以方面的查出来,但是MySQL没有这些函数,没有直接的方法可以查出来,可通过 ...
- 记一次有意思的 SQL 实现 → 分组后取每组的第一条记录
开心一刻 今天,朋友气冲冲的走到我面前 朋友:我不是谈了个女朋友,谈了三个月嘛,昨天我偷看她手机,你猜她给我备注什么 我:备注什么? 朋友:舔狗 2 号! 我一听,气就上来了,说道:走,找她去,这婆娘 ...
- Mysql相关子查询&&MySQL获取分组后的TOP N记录
小燕子,哈哈哈哈~~~~~~~~~~ 相关子查询是指引用了外部查询列的子查询,即子查询会对外部查询的每行进行一次计算. 举个例子 root:test> show create table tes ...
- 【转】Mysql相关子查询&&MySQL获取分组后的TOP N记录
https://www.cnblogs.com/Yiran583/p/6743870.html select * from test1 a where 2 > (select count(*) ...
- 获取分组后统计数量最多的纪录;limit用法;sql执行顺序
CREATE TABLE emp(id INT PRIMARY KEY,NAME VARCHAR(11),dep_id INT ,salary INT); CREATE TABLE dept(id I ...
- MySQL 取分组后每组的最新记录
修改<常用SQL之日期格式化和查询重复数据>中表test1的创建时间,修改后的测试数据如下: 以姓名分组后提取每组最新创建的记录: SELECT a.* FROM test1 AS a, ...
- SQL Server 分组后取Top N
SQL Server 分组后取Top N(转) 近日,工作中突遇一需求:将一数据表分组,而后取出每组内按一定规则排列的前N条数据.乍想来,这本是寻常查询,无甚难处.可提笔写来,终究是困住了笔者好一会儿 ...
- SQL 分组后获取其中一个字段最大值的整条记录
--有id,name,createDate的一张表testTable--根据name分组,获取每组中createDate最大的那条记录(整条)查询出来------------------------- ...
随机推荐
- Jsp电子商务之七 订单篇2
从View页面,点击超链接查询订单,进入到控制器 OrderlistServlet package com.cart.web; import java.io.IOException; import j ...
- sass的循环for,while,each
1. for @for $i from 1 to 10 { .border-#{$i} { border: #{$i}px solid blue; } } 2. while $i: 6; @while ...
- 【线段树】【P3740】 [HAOI2014]贴海报
传送门 Description Bytetown城市要进行市长竞选,所有的选民可以畅所欲言地对竞选市长的候选人发表言论.为了统一管理,城市委员会为选民准备了一个张贴海报的electoral墙. 张贴规 ...
- JS获取移动端系统信息(操作系统、操作系统版本、横竖屏状态、设备类型、网络状态、生成浏览器指纹)
function getOS() { // 获取当前操作系统 var os; if (navigator.userAgent.indexOf('Android') > -1 || navigat ...
- [freemarker篇]03.如何处理空值
我想说的一点,我写的东西没有那么权威,这都是我实际开发中使用的,可能缺少很多! 例如这篇要说的如何处理空值,我发现我使用的跟网上很多写的不太一样,我也没有过多的去尝试网上的那么多写法! 抱歉,我只是写 ...
- [洛谷P2051] [AHOI2009]中国象棋
洛谷题目链接:[AHOI2009]中国象棋 题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法 ...
- MySQL和Postgresql的区别
一.PostgreSQL相对于MySQL的优势 1.在SQL的标准实现上要比MySQL完善,而且功能实现比较严谨:2.存储过程的功能支持要比MySQL好,具备本地缓存执行计划的能力:3.对表连接支持较 ...
- os.fork()
ret = os.fork() if ret == 0: child_suite # 子进程代码 else: parent_suite # 父进程代码 Python中的fork() 函数可以获得系统中 ...
- activemq依赖包获取
现在项目中使用的是activemq-all.jar的jar,17M多,里面集成了日志.spring等相关的包.但项目启动时发现系统使用的是activemq包中的日志实现,没有用本项目的日志包.只能将整 ...
- Zen Cart、Joy-Cart、Magento、ShopEX、ECshop电子商务系统比较
1.Zen Cart 优点:历史较久,系统经过长时间充分的测试,比较成熟:免费开源便于功能二次开发:基础功能强大:安装插件简单,修改文件很少,甚至不用修改文件:应用非常广泛,插件.模块更新快,其中多为 ...