Leetcode1412.查找成绩处于中游的学生(困难)

题目
Table: Student

+---------------------+---------+
| Column Name         | Type    |
+---------------------+---------+
| student_id          | int     |
| student_name        | varchar |
+---------------------+---------+

student_id is the primary key for this table.
student_name is the name of the student.

Table: Exam

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| exam_id       | int     |
| student_id    | int     |
| score         | int     |
+---------------+---------+

(exam_id, student_id) is the primary key for this table.
Student with student_id got score points in exam with id exam_id.

A "quite" student is the one who took at least one exam and didn't score neither the high score nor the low score.

Write an SQL query to report the students (student_id, student_name) being "quiet" in ALL exams.

Don't return the student who has never taken any exam. Return the result table ordered by student_id.

The query result format is in the following example.

Student table:

+-------------+---------------+
| student_id  | student_name  |
+-------------+---------------+
| 1           | Daniel        |
| 2           | Jade          |
| 3           | Stella        |
| 4           | Jonathan      |
| 5           | Will          |
+-------------+---------------+

Exam table:

+------------+--------------+-----------+
| exam_id    | student_id   | score     |
+------------+--------------+-----------+
| 10         |     1        |    70     |
| 10         |     2        |    80     |
| 10         |     3        |    90     |
| 20         |     1        |    80     |
| 30         |     1        |    70     |
| 30         |     3        |    80     |
| 30         |     4        |    90     |
| 40         |     1        |    60     |
| 40         |     2        |    70     |
| 40         |     4        |    80     |
+------------+--------------+-----------+

Result table:

+-------------+---------------+
| student_id  | student_name  |
+-------------+---------------+
| 2           | Jade          |
+-------------+---------------+

For exam 1: Student 1 and 3 hold the lowest and high score respectively.
For exam 2: Student 1 hold both highest and lowest score.
For exam 3 and 4: Studnet 1 and 4 hold the lowest and high score respectively.
Student 2 and 5 have never got the highest or lowest in any of the exam.
Since student 5 is not taking any exam, he is excluded from the result.
So, we only return the information of Student 2.

生成数据

CREATE TABLE Student3(
student_id         INT,     
student_name       VARCHAR(20));

CREATE TABLE Exam(
exam_id       INT,
student_id    INT,
score         INT);

INSERT INTO Student3 VALUE(1, 'Daniel'),(2, 'Jade'),(3, 'Stella'),(4, 'Jonathan'),(5, 'Will');

INSERT INTO Exam VALUE(10, 1, 70),(10, 2, 80),(10, 3, 90),(20, 1, 80),
(30, 1, 70),(30, 3, 80),(30, 4, 90),
(40, 1, 60),(40, 2, 70),(40, 4, 80);

解答
就是选出在每一门课中都没有取到最高分也没有取到最低分的同学 但是他得参加考试
对exam_id进行分组 可以得到最高分和最低分
用二元in可以选出得到过最低分和最高分的同学
在exam中排除以上的同学即可
最后和Student 表左连接

先选出最高分和最低分

SELECT E.`exam_id`, MAX(E.`score`) AS max_sc
FROM Exam AS E
GROUP BY E.`exam_id`
UNION
SELECT E.`exam_id`, MIN(E.`score`) AS min_sc
FROM Exam AS E
GROUP BY E.`exam_id`;

再选出得到过最高分或最低分的同学

SELECT DISTINCT EEE.`student_id`
FROM Exam AS EEE
WHERE (EEE.`exam_id`, EEE.`score`) IN (SELECT E.`exam_id`, MAX(E.`score`) AS max_sc
FROM Exam AS E
GROUP BY E.`exam_id`
UNION
SELECT E.`exam_id`, MIN(E.`score`) AS min_sc
FROM Exam AS E
GROUP BY E.`exam_id`);

排除以上的同学

SELECT DISTINCT EE.`student_id`
FROM Exam AS EE
WHERE EE.`student_id` NOT IN (SELECT DISTINCT EEE.`student_id`
FROM Exam AS EEE
WHERE (EEE.`exam_id`, EEE.`score`) IN (SELECT E.`exam_id`, MAX(E.`score`) AS max_sc
FROM Exam AS E
GROUP BY E.`exam_id`
UNION
SELECT E.`exam_id`, MIN(E.`score`) AS min_sc
FROM Exam AS E
GROUP BY E.`exam_id`));

最后两表连接即可 左连接

SELECT S.`student_id`, S.`student_name`
FROM (SELECT DISTINCT EE.`student_id`
FROM Exam AS EE
WHERE EE.`student_id` NOT IN (SELECT DISTINCT EEE.`student_id`
FROM Exam AS EEE
WHERE (EEE.`exam_id`, EEE.`score`) IN (SELECT E.`exam_id`, MAX(E.`score`) AS max_sc
FROM Exam AS E
GROUP BY E.`exam_id`
UNION
SELECT E.`exam_id`, MIN(E.`score`) AS min_sc
FROM Exam AS E
GROUP BY E.`exam_id`))) AS tmp
LEFT JOIN Student3 AS S
ON tmp.student_id = S.`student_id`;

你可能感兴趣的:(Leetcode1412.查找成绩处于中游的学生(困难))