Mysql 找出至少参加过一次考试但没有最高或最低分数的学生
我的解决方案通过了第一个测试用例,但最终提交后得到了错误的答案。我感谢任何愿意指出我错误的人。谢谢 问题如下:Mysql 找出至少参加过一次考试但没有最高或最低分数的学生,mysql,sql,inner-join,having-clause,Mysql,Sql,Inner Join,Having Clause,我的解决方案通过了第一个测试用例,但最终提交后得到了错误的答案。我感谢任何愿意指出我错误的人。谢谢 问题如下: -- get eligible student with eligible_student as ( select distinct student_id as eligible_id from Exam group by 1 order by 1 ), -- get the high and low score high_low as (select studen
-- get eligible student
with eligible_student as
(
select distinct student_id as eligible_id from Exam
group by 1
order by 1
),
-- get the high and low score
high_low as
(select student_id, max(score) as high_score, min(score) as low_score
from Exam),
result as
(select eligible_student.eligible_id as student_id
from eligible_student inner join
high_low
on eligible_student.eligible_id <> high_low.student_id
-- left join Student
-- on eligible_student.eligible_id = Student.student_id
group by student_id
order by student_id
)
select result.student_id, s.student_name as student_name
from result left join Student s
on result.student_id = s.student_id
order by student_id;
表:学生
+---------------------+---------+
| Column Name | Type |
+---------------------+---------+
| student_id | int |
| student_name | varchar |
+---------------------+---------+
student_id是此表的主键。
student_name是学生的名字
表:考试
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| exam_id | int |
| student_id | int |
| score | int |
+---------------+---------+
考试id、学生id是此表的主键。
有学生证的学生在有学生证的考试中得到分数
一个安静的学生是指至少参加过一次考试,并且没有得到高分和低分的学生
编写一个SQL查询以报告学生id,学生姓名在所有考试中保持安静
不要退回从未参加过任何考试的学生。返回按学生id排序的结果表
查询结果格式如下例所示
学生表:
+-------------+---------------+
| student_id | student_name |
+-------------+---------------+
| 1 | Daniel |
| 2 | Jade |
| 3 | Stella |
| 4 | Jonathan |
| 5 | Will |
+-------------+---------------+
检查表:
+------------+--------------+-----------+
| 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 |
+------------+--------------+-----------+
结果表:
+-------------+---------------+
| student_id | student_name |
+-------------+---------------+
| 2 | Jade |
+-------------+---------------+
问题的解释:
对于考试1:学生1和3分别得分最低和最高。
对于第二次考试:学生1的分数最高和最低。
对于考试3和4:Studnet 1和4分别获得最低和最高分数。
学生2和5从未在任何一次考试中获得过最高或最低分数。
由于5号学生没有参加任何考试,他被排除在结果之外。
因此,我们只返回学生2的信息
我的答案是创建两个表格,一个是列出符合条件的学生,至少有一次考试。
另一个是查找考试表的maxscore和minscore。
并使用找到安静的学生id,然后加入学生表查找
此学生id的名称,如下所示:
-- get eligible student
with eligible_student as
(
select distinct student_id as eligible_id from Exam
group by 1
order by 1
),
-- get the high and low score
high_low as
(select student_id, max(score) as high_score, min(score) as low_score
from Exam),
result as
(select eligible_student.eligible_id as student_id
from eligible_student inner join
high_low
on eligible_student.eligible_id <> high_low.student_id
-- left join Student
-- on eligible_student.eligible_id = Student.student_id
group by student_id
order by student_id
)
select result.student_id, s.student_name as student_name
from result left join Student s
on result.student_id = s.student_id
order by student_id;
我将使用窗口函数和聚合:
select s.*
from student s
inner join (
select e.*,
rank() over(partition by exam_id order by score) as rn_asc,
rank() over(partition by exam_id order by score desc) as rn_desc
from exam e
) e on e.student_id = s.student_id
group by s.student_id
having min(rn_asc) > 1 and min(rn_desc) > 1
子查询通过分数的升序和降序对具有相同考试的记录进行排序,允许平分。然后,我们可以将其与学生表连接起来,该表消除了根本没有考试的学生,按学生分组,并筛选两个等级都未达到1的学生。此查询:
SELECT *,
(MIN(score) OVER (PARTITION BY exam_id) = score) +
(MAX(score) OVER (PARTITION BY exam_id) = score) flag
FROM exam
当学生的分数既不是考试的最低分也不是最高分时,返回一个值为0的标志列
您可以根据上述查询的结果进行聚合,以获得没有一个值不同于0的标志的所有学生:
或:
看。
结果:
这部分是错误的:
with high_low as
(select student_id, max(score) as high_score, min(score) as low_score
from Exam)
因为它输出:
+------------+------------+-----------+
| student_id | high_score | low_score |
+------------+------------+-----------+
| 1 | 90 | 60 |
+------------+------------+-----------+
而student_id=1与发现的高_分数或低_分数无关
在此之后,在选择cte结果时使用找到但不正确的学生id
解决方案:
with high_low as
(select max(score) as high_score, min(score) as low_score
from Exam)
select student.student_id, student_name
from (
select exam.student_id
from exam
group by exam.student_id
having max(score) <> (select high_score from high_low)
and min(score) <> (select low_score from high_low)) x
inner join student on student.student_id=x.student_id;
谢谢你的回复!我可以问一下排名,但排名会有差距,对吗?或者这不重要,因为我们只关心最大值和最小值。谢谢@陈:是的,职级上可能有差距,但实际上这并不重要,因为我们只看最高层和最底层的职级。
+------------+------------+-----------+
| student_id | high_score | low_score |
+------------+------------+-----------+
| 1 | 90 | 60 |
+------------+------------+-----------+
with high_low as
(select max(score) as high_score, min(score) as low_score
from Exam)
select student.student_id, student_name
from (
select exam.student_id
from exam
group by exam.student_id
having max(score) <> (select high_score from high_low)
and min(score) <> (select low_score from high_low)) x
inner join student on student.student_id=x.student_id;
select
student.*
from exam
inner join student on student.student_id=exam.student_id
group by student_id
having max(score) not in (select max(score) from exam)
and min(score) not in (select min(score) from exam);