Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 找出至少参加过一次考试但没有最高或最低分数的学生_Mysql_Sql_Inner Join_Having Clause - Fatal编程技术网

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);