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)
MySQL获取分组后的TOP 1和TOP N记录-转的更多相关文章
- SQL获取分组后取某字段最大一条记录(求每个类别中最大的值的列表)
获取分组后取某字段最大一条记录 方法一:(效率最高) select * from test as a where typeindex = (select max(b.typeindex) from t ...
- 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(*) ...
- 获取分组后的TOP 1和TOP N记录
MySQL获取分组后的TOP 1和TOP N记录 有时会碰到一些需求,查询分组后的最大值,最小值所在的整行记录或者分组后的top n行的记录,在一些别的数据库可能有窗口函数可以方面的查出来,但是MyS ...
- MySQL 对分组后的同类数据进行拼接字符串
MySQL 对分组后的同类数据进行拼接字符串 写后台方法时遇到个问题,需要将表内同一订单号的操作记录流水进行简单拼接输出,不想取出来再操作,找了个mysql的方法直接操作 //group_concat ...
- MySQL 取分组后每组的最新记录
修改<常用SQL之日期格式化和查询重复数据>中表test1的创建时间,修改后的测试数据如下: 以姓名分组后提取每组最新创建的记录: SELECT a.* FROM test1 AS a, ...
- 记一次有意思的 SQL 实现 → 分组后取每组的第一条记录
开心一刻 今天,朋友气冲冲的走到我面前 朋友:我不是谈了个女朋友,谈了三个月嘛,昨天我偷看她手机,你猜她给我备注什么 我:备注什么? 朋友:舔狗 2 号! 我一听,气就上来了,说道:走,找她去,这婆娘 ...
- Mysql 数据分组取某字段值所有最大的记录行
需求: 表中同一个uid(用户)拥有多条游戏等级记录,现需要取所有用户最高等级(level)的那一条数据,且时间(time)越早排越前.这是典型的排名表 +------+-------+------- ...
- Mysql获取去重后的总数
如果一张表中某个字段存在重复的值,现在我想去重后获取这个字段值的总数 先看这张表 这张表中的openid有重复值 怎么通过sql语句获取openid的去重总数呢 select count(distin ...
随机推荐
- JS 判断object是否包含某个键
1. myObj.hasOwnProperty('myKey'); 2. if ('key' in myObj)
- SNF快速开发平台MVC-表格单元格合并组件
1. 表格单元格合并组件 1.1. 效果展示 1.1.1. 页面展现表格合并单元格 图 4.1 1.1.2. 导出excel合并单元格 图 4.2 1.2. 调用说 ...
- [转]设备唯一标识方法(Unique Identifier):如何在Windows系统上获取设备的唯一标识
原文地址:http://www.vonwei.com/post/UniqueDeviceIDforWindows.html 唯一的标识一个设备是一个基本功能,可以拥有很多应用场景,比如软件授权(如何保 ...
- golang slice
golang 在for range一个slice时,会读出其cap长度.在for的过程中,即使动态append该slice,最终for也会在第一次读取的cap长度处停止. package main i ...
- 用Python来玩微信跳一跳
微信2017年12月28日发布了新版本,在小程序里面有一个跳一跳小游戏,试着点一点玩了下.第二天刚好在一篇技术公众号中,看到有大神用Python代码计算出按压时间,向手机发送android adb命令 ...
- Android中获取应用程序(包)的信息-----PackageManager的使用
本节内容是如何获取Android系统中应用程序的信息,主要包括packagename.label.icon.占用大小等.具体分为两个 部分,计划如下: 第一部分: 获取应用程序的packagename ...
- python开发-与其他语言的比较
1.关于函数 1)不需要指定返回类型,不需要指定是否有返回值,每个函数都有返回值,没有的话,就返回None 2)参数也可以不指定类型,可以有默认参数,但是必须放到最后,调用的时候指定参数的值,和顺序无 ...
- nginx配置http为1.0到1.1
转载自:https://blog.csdn.net/u014558668/article/details/79237020 需求:接口通过nginx转发服务器,接收不到数据,但是测试环境是好的: 环境 ...
- 模仿Semaphore自定义自己的 信号量
简介 这里模仿Semaphore,自定义自己的信号量,利用AQS共享模式 1.MySemaphore.java package com.jacky; import java.util.concurre ...
- Linux初始化init系统-Sysvinit、Upstart、Systemd
首先了解以下Ubuntu运行级别(init)对应工具的变化历史: 1.Ubuntu 6.10及以前版本使用Sysvinit. 2.Ubuntu 14.10及以前版本使用Upstart但是还留着Sysv ...