MySQL group summary takes the first N records

Posted by ltd on Sun, 29 Dec 2019 20:12:42 +0100

score table:

CREATE TABLE `score` (
  `student_id` int(10) DEFAULT NULL,
  `class_id` int(10) DEFAULT NULL,
  `score` int(5) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

Field student ID student ID, class ID: class ID, score: Score
Data preparation:

insert into score values(1,1,100),(2,1,93),(3,1,89),(4,1,96),(5,2,98),(6,2,97),(7,2,90),(8,2,88),(9,1,96);

The table structure is as follows:

mysql> select * from score;
+------------+----------+-------+
| student_id | class_id | score |
+------------+----------+-------+
|          1 |        1 |   100 |
|          2 |        1 |    93 |
|          3 |        1 |    89 |
|          4 |        1 |    96 |
|          5 |        2 |    98 |
|          6 |        2 |    97 |
|          7 |        2 |    90 |
|          8 |        2 |    88 |
|          9 |        1 |    96 |
+------------+----------+-------+
9 rows in set (0.00 sec)

1. Take the top two students of each class (including the second in parallel)

mysql> select * 
from score s1 
where (select count(0) from score s2 where s1.class_id = s2.class_id and s1.score < s2.score) < 2;
+------------+----------+-------+
| student_id | class_id | score |
+------------+----------+-------+
|          1 |        1 |   100 |
|          4 |        1 |    96 |
|          5 |        2 |    98 |
|          6 |        2 |    97 |
|          9 |        1 |    96 |
+------------+----------+-------+
5 rows in set (0.00 sec)

sql explanation: take the data in table s1. For the data with the same class ID and s2 class ID, the data entry of s2, which is larger than the score score of s1, must be less than 2

Or use left join:

mysql> select s1.* 
from score s1 
left join score s2 on s1.class_id = s2.class_id and s1.score<s2.score 
group by s1.class_id,s1.student_id,s1.score 
having count(s2.student_id)<2;
+------------+----------+-------+
| student_id | class_id | score |
+------------+----------+-------+
|          1 |        1 |   100 |
|          4 |        1 |    96 |
|          9 |        1 |    96 |
|          5 |        2 |    98 |
|          6 |        2 |    97 |
+------------+----------+-------+
5 rows in set (0.00 sec)

2. Take student score data and represent ranking

mysql> select s1.*,(select count(0) + 1 from score s2 where s2.score > s1.score)rank from score s1;
+------------+----------+-------+------+
| student_id | class_id | score | rank |
+------------+----------+-------+------+
|          1 |        1 |   100 |    1 |
|          2 |        1 |    93 |    6 |
|          3 |        1 |    89 |    8 |
|          4 |        1 |    96 |    4 |
|          5 |        2 |    98 |    2 |
|          6 |        2 |    97 |    3 |
|          7 |        2 |    90 |    7 |
|          8 |        2 |    88 |    9 |
|          9 |        1 |    96 |    4 |
+------------+----------+-------+------+
9 rows in set (0.00 sec)

sql explanation: just display the items in s2 that have larger scores than those in s1 (add 1 for count)

3. Take student performance data to show class ranking

mysql> select s1.*
,(select count(0) + 1 
from score s2 
where s1.class_id = s2.class_id 
and s2.score > s1.score
)rank 
from score s1 
order by class_id,rank;
+------------+----------+-------+------+
| student_id | class_id | score | rank |
+------------+----------+-------+------+
|          1 |        1 |   100 |    1 |
|          4 |        1 |    96 |    2 |
|          9 |        1 |    96 |    2 |
|          2 |        1 |    93 |    4 |
|          3 |        1 |    89 |    5 |
|          5 |        2 |    98 |    1 |
|          6 |        2 |    97 |    2 |
|          7 |        2 |    90 |    3 |
|          8 |        2 |    88 |    4 |
+------------+----------+-------+------+
9 rows in set (0.00 sec)

Same as before, but only the same data items of the class need to be calculated in the filter condition

4. Take the top two of each class (only the data in front will be taken in parallel)

Reference documents:
https://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql

Topics: MySQL SQL less