MYSQL8 query each person's top three subjects or the top three scores of each subject

topic

There are 2 tables, user table, score table

  • 1. Find out the top three subjects in each person's grades
  • 2. Find out the top three results of each subject
-- 用户表
CREATE TABLE `user_info` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `age` int DEFAULT NULL,
  `email` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- 用户数据
INSERT INTO `user_info`(`id`, `name`, `age`, `email`) VALUES (1, 'moss', 33, '[email protected]');
INSERT INTO `user_info`(`id`, `name`, `age`, `email`) VALUES (2, 'jim', 25, '[email protected]');
INSERT INTO `user_info`(`id`, `name`, `age`, `email`) VALUES (3, 'tom', 18, '[email protected]');

-- 成绩表
CREATE TABLE `user_course` (
  `id` int NOT NULL AUTO_INCREMENT,
  `user_id` int DEFAULT NULL,
  `course` varchar(30) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `score` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- 成绩数据
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (1, 1, '语文', 90);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (2, 1, '数学', 66);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (3, 1, '英语', 80);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (4, 1, '物理', 50);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (5, 1, '综合', 100);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (6, 2, '语文', 88);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (7, 2, '数学', 70);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (8, 2, '英语', 99);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (9, 2, '政治', 70);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (10, 2, '艺术', 66);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (11, 3, '语文', 68);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (12, 3, '画画', 80);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (13, 3, '化学', 70);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (14, 3, '英语', 98);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (15, 4, '语文', 80);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (16, 4, '英语', 88);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (17, 4, '数学', 90);
INSERT INTO `user_course`(`id`, `user_id`, `course`, `score`) VALUES (18, 4, '历史', 99);

User Data
insert image description here
Grade Data
insert image description here

1. Find out the top three subjects in each person's grades

problem solving ideas
  • Step 1: The grade table is ranked according to the subject scores of each person to obtain the subject score ranking of each person
SELECT c1.user_id, c1.course, c1.score, (
		SELECT count(DISTINCT c2.score)
		FROM user_course c2 
		WHERE c1.score < c2.score
			AND c1.user_id = c2.user_id
	) + 1 AS num
FROM user_course c1 
ORDER BY c1.user_id, num

ranking result
insert image description here

  • The second step: name the result set obtained in the first step c3, and then query the num less than or equal to 3 in c3 and sort them by subject
SELECT c3.user_id, c3.course, c3.score
FROM (
	SELECT c1.user_id, c1.course, c1.score, (
			SELECT count(DISTINCT c2.score)
			FROM user_course c2 
			WHERE c1.score < c2.score
				AND c1.user_id = c2.user_id
		) + 1 AS num
	FROM user_course c1 
	HAVING num <= 3
	ORDER BY c1.user_id, num
) c3 
ORDER BY c3.user_id ASC, c3.score DESC

result
insert image description here

  • Step 3: Perform a left join on the final query result and the user_info table to find out the user name
select u.name, c4.course, c4.score 
from user_info u 
LEFT JOIN (
	SELECT c3.user_id, c3.course, c3.score
	FROM (
		SELECT c1.user_id, c1.course, c1.score, (
				SELECT count(DISTINCT c2.score)
				FROM user_course c2 
				WHERE c1.score < c2.score
					AND c1.user_id = c2.user_id
			) + 1 AS num
		FROM user_course c1 
		HAVING num <= 3
		ORDER BY c1.user_id, num
	) c3 
	ORDER BY c3.user_id ASC, c3.score DESC
) c4 ON u.id = c4.user_id

result
insert image description here

2. Find out the top three results of each subject

The idea is the same as above, first rank according to the results of each subject, and then filter out the top 3

SELECT c3.user_id, c3.course, c3.score
FROM (
	SELECT c1.user_id, c1.course, c1.score, (
			SELECT count(DISTINCT c2.score)
			FROM user_course c2 
			WHERE c1.score <= c2.score
				AND c1.course = c2.course
		) AS num
	FROM user_course c1 
	HAVING num <= 3 
	ORDER BY c1.course, c1.score desc 
) c3 

result
insert image description here

Guess you like

Origin blog.csdn.net/q283614346/article/details/130841342