mysql 为什么这个带有“where not in”子句的SQL查询不能像预期的那样工作?

sdnqo3pr  于 2024-01-05  发布在  Mysql
关注(0)|答案(1)|浏览(112)

下面是这个问题的SQL Fiddle
以下是输入表:
学生桌:
| 学生ID|学生姓名|
| --|--|
| 1 |丹尼尔|
| 2 |玉|
| 3 |Stella|
| 4 |乔纳森|
| 5 |将|
检查床:
| 检查ID|学生ID|评分|
| --|--|--|
| 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)。从未参加过任何考试的学生不应该包括在结果中。
对于上下文,这是一个面试准备问题,我已经通过其他方式解决了它。我特别试图理解为什么下面的查询不起作用。

with student_scores as (
select student_id, student_name, 
rank() over (partition by exam_id order by score asc) worse_rank,
rank() over (partition by exam_id order by score desc) best_rank

from Student
inner join Exam using (student_id)
)

select distinct student_id, student_name
from student_scores
where student_id not in (

select student_id
from student_scores
where ((worse_rank=1) or (best_rank=1)) and (student_id is not null)
)

字符串
但是,这不会返回任何记录,而我希望返回student_id 2 Jade的记录。
我在调试时发现的一些事情:
1.如果我像这样使用另一个CTE,它就可以工作:

loud as (
  select distinct student_id
  from student_scores
  where ((worse_rank=1) or (best_rank=1)) and (student_id is not null)
)


然后用

where student_id not in (select student_id from loud)


但这只适用于我在额外的CTE中使用distinct
1.如果我通过显式地将student_id定义为PRIMARY KEY来创建输入表,它就可以工作。
1.如果我在where not in子句中使用student_name而不是student_id,它也可以工作。
1.在where not in子句之后向子查询添加distinct没有帮助。

vzgqcmou

vzgqcmou1#

在这里,我将使用一种聚合方法,并借助RANK()窗口函数:

WITH cte AS (
    SELECT *, RANK() OVER (PARTITION BY exam_id ORDER BY score) rnk1,
              RANK() OVER (PARTITION BY exam_id ORDER BY score DESC) rnk2
    FROM Exam
)

SELECT s.student_id, s.student_name
FROM Student s
INNER JOIN cte t
    ON t.student_id = s.student_id
GROUP BY s.student_id, s.student_name
HAVING SUM(t.rnk1 = 1) = 0 AND SUM(t.rnk2 = 1) = 0;

字符串
HAVING子句Assert任何匹配的学生在任何考试中都不是最低或最高分。

相关问题