mysql取每个分组内前n条数据

说明

注:本文的数据表,以及数据都仅供测试使用,请不要纠结于其命名及数据内容,这样只会浪费你的时间哦!

  1. 有些人看到标题,可能首先想到的就是 GROUP BY ,那么,先见到介绍一下它。 mysql 日常使用中,GROUP BY 基本是无处不在了,其作用大概可以分为两类,第一个就是去重;第二个是为了聚合函数使用。
  2. 本文介绍的知识点正是基于 GROUP BY 的,常见的使用是,将某个信息分组,求数量。例如:在某个人员信息表中,性别为 男 和 女 的人数分别有多少个,可以使用以下SQL语句:
SELECT sex AS `性别`, count(*) as `人数` FROM  person;
  1. 如果你想查看收入前 5 的人的信息,你可以使用下面的SQL语句来实现:
SELECT * FROM  person ORDER BY salary DESC limit 5;
# 以工资倒序,取前 5

本文重点

需求: 需要查询人员信息表中,每个地方工资排名 前三 的人员信息
分析: limit去能取全部的前三条,那怎么能取得每个地方工资排在前三的人的数据呢?
SQL 语句如下:

SET @tmpAddress = "";#初始化很重要,否则会影响首次执行结果
SET @rank = 1;#初始化很重要,否则会影响首次执行结果
SELECT uName, sex, salary, address
FROM 
(
	SELECT uName, sex, salary, address,
	IF(@tmpAddress = address, @rank:=@rank + 1, @rank:=1) as new_rank,
	@tmpAddress := address AS tmpAddress
	FROM (SELECT * FROM person ORDER BY address, salary DESC) tb_a
) tb
WHERE new_rank <= 3;

查询结果(表中所有数据展示在本文最后面):
在这里插入图片描述
SQL说明
1、 首先将所有结果查出,并且给每个地址中的每条数据增加唯一标识符(递增),相当于将数据以 地址分组,每组中的数据都有一个序号 new_rank,表示当前数据是当前分组中的第几条;
2、 @tmpAddress := address 定义了一个变量,变量的值为 address,没次都将当前数据中的 address 赋值给 @tmpAddress 变量;
3、 语句解析:

IF(@tmpAddress = address, @rank:=@rank + 1, @rank:=1)
# 如果 @tmpAddress 变量的值和当前 address相同,则序号加1,否则,序号从1开始重新计数
# @tmpAddress 据上一步说明,@tmpAddress 应该存储的是上一个 address 的值
# 注:那么要想序号连续增加,就必须用 ORDER BY address,保证相同的地址可以连续计数

4、查询完成后 new_rank 中存储的将是每条数据在每个(地址分组)中的唯一序号,然后过滤序号小于 3 的则是每个分组的前三个。

注意: 中间查询过程中的 ORDER BY 语句必不可少,首先是地址,因为相同的地址必须放在一起,才能保证生成的序号的准确性,然后是工资排序。

附录

表中所有数据:
在这里插入图片描述
生成测试数据表的语句:

CREATE TEMPORARY TABLE person (
	mykey INT NOT NULL AUTO_INCREMENT,
	uName VARCHAR(255),			#姓名
	sex VARCHAR(10),			#性别
	salary INT,					#工资
	address VARCHAR(255),		#住址	
	PRIMARY KEY (mykey)
);
#为了方便大家更快速的了解本篇文章的内容,特附上测试数据插入语句,以节约大家模拟数据的时间
INSERT INTO person(uName, sex, salary, address) VALUES("七少睿", "男", 20000, "北京");
INSERT INTO person(uName, sex, salary, address) VALUES("七美瑞", "女", 13000, "北京");
INSERT INTO person(uName, sex, salary, address) VALUES("七洪海", "男", 10000, "北京");
INSERT INTO person(uName, sex, salary, address) VALUES("七程瑜", "女", 18000, "北京");
INSERT INTO person(uName, sex, salary, address) VALUES("七翔浩", "男", 12000, "北京");
INSERT INTO person(uName, sex, salary, address) VALUES("七树顺", "男", 9000, "北京");
INSERT INTO person(uName, sex, salary, address) VALUES("七然平", "男", 11000, "上海");
INSERT INTO person(uName, sex, salary, address) VALUES("宸博", "男", 90000, "天津");
INSERT INTO person(uName, sex, salary, address) VALUES("然弘", "男", 13000, "上海");
INSERT INTO person(uName, sex, salary, address) VALUES("凯慕", "男", 16000, "北京");
INSERT INTO person(uName, sex, salary, address) VALUES("军晟", "男", 18000, "上海");
INSERT INTO person(uName, sex, salary, address) VALUES("仁阳", "男", 12000, "北京");
INSERT INTO person(uName, sex, salary, address) VALUES("瑗钰", "女", 7000, "天津");
INSERT INTO person(uName, sex, salary, address) VALUES("伊阳", "女", 11000, "上海");
INSERT INTO person(uName, sex, salary, address) VALUES("安钰", "女", 12000, "北京");
INSERT INTO person(uName, sex, salary, address) VALUES("锳仙", "女", 9000, "北京");
INSERT INTO person(uName, sex, salary, address) VALUES("彤雅", "女", 11000, "上海");
INSERT INTO person(uName, sex, salary, address) VALUES("澈漫", "女", 12800, "上海");
INSERT INTO person(uName, sex, salary, address) VALUES("冰妙", "女", 9500, "天津");
INSERT INTO person(uName, sex, salary, address) VALUES("深洁", "女", 10500, "天津");
INSERT INTO person(uName, sex, salary, address) VALUES("雯璐", "女", 13000, "上海");
INSERT INTO person(uName, sex, salary, address) VALUES("亮雅", "女", 6000, "天津");
INSERT INTO person(uName, sex, salary, address) VALUES("滢玲", "女", 14000, "上海");

猜你喜欢

转载自blog.csdn.net/qq_33191599/article/details/106188598
今日推荐