mysql gets the first n data in each group

illustrate

Note: The data table and data in this article are for testing purposes only. Please do not get hung up on the naming and data content, as this will only waste your time!

  1. When some people see the title, the first thing they think of is GROUP BY , so let’s introduce it first. In the daily use of mysql , GROUP BY is basically everywhere, and its functions can be roughly divided into two categories. The first is to remove duplicates; the second is to use aggregate functions.
  2. The knowledge points introduced in this article are based on GROUP BY . A common use is to group certain information and find the quantity. For example: in a certain personnel information table, you can use the following SQL statement to determine how many people are male and female:
SELECT sex AS `性别`, count(*) as `人数` FROM  person;
  1. If you want to view the information of the top 5 earners, you can use the following SQL statement to achieve this:
SELECT * FROM  person ORDER BY salary DESC limit 5;
# 以工资倒序,取前 5

Focus of this article

Requirement: In the personnel information table, we need to query the information analysis of the top three people in each place with the highest salary: Limit can get all the top three items, so how can we get the data of the top three people in each place with the highest salary? The SQL statement is as follows:

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;

Query results (all data in the table are shown at the end of this article):
Insert image description here
SQL instructions :
1. First, find out all the results, and add a unique identifier (increment) to each piece of data in each address , which is equivalent to converting the data to an address . Grouping , the data in each group has a serial number new_rank , indicating which item the current data is in the current group;
2. @tmpAddress:= address defines a variable, the value of the variable is address, and the current data is included every time The address is assigned to the @tmpAddress variable;
3. Statement analysis:

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

4. After the query is completed, what is stored in new_rank will be the unique serial number of each piece of data in each ( address group ), and then the first three of each group will be filtered if the serial number is less than 3 .

Note: The ORDER BY statement in the intermediate query process is essential . The first is the address , because the same addresses must be placed together to ensure the accuracy of the generated serial numbers , and then the salary sorting.

appendix

All data in the table:
Insert image description here
statement to generate test data table:

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, "上海");

Guess you like

Origin blog.csdn.net/qq_33191599/article/details/106188598