学位课程中每门课程都参加过考试的学生

时间:2018-10-29 20:33:55

标签: sql postgresql

我一直在尝试采用一种“不存在”的方法来隔离答案,但是我认为我做的太深了。实际上,我仅限于使用真正基础的东西作为数据库类的介绍。因此,基本上只有INNER JOIN,UNION和CASE以及其他一些东西,但可能最好像裸骨头一样假设。我们还不允许使用合并。

3 个答案:

答案 0 :(得分:0)

不确定仅使用INNER JOIN,UNION和CASE是否可以实现->但我找到了使用外部联接的解决方案(仍然非常简单)。

让我们尝试通过两个步骤来解决这个问题。

1)让我们看看哪些学生尚未完成所有课程

select s.code
  from  programs p inner join students s on (p.degree = s.degree)
                   left outer join exams e on (e.course = p.course and e.student = s.code)
  where e.course is null

我们与学生一起参加计划,然后让外部参加考试,并仅过滤那些无法匹配考试行的行(这意味着学生尚未参加考试)

2)我们得到此查询未返回的所有学生(表示他们已完成所有必修课程)

select
code, name
from student where code not in (

  select s.code
  from  programs p inner join students s on (p.degree = s.degree)
                   left outer join exams e on (e.course = p.course and e.student = s.code)
  where e.course is null

)

答案 1 :(得分:0)

我喜欢对这些东西使用聚合。

select s.code, s.name, s.degree
from students s join
     programs p
     on p.degree = s.degree join
     exams e
     on e.student = s.code and e.course = p.course
group by s.code, s.name, s.degree
having count(distinct e.course) = (select count(*) from programs p2 where p2.degree = p.degree);

请注意,这包括degree以及学生。毕竟,学生可以双修专业。

答案 2 :(得分:0)

与Preli的回答类似,我将使用左联接突出显示尚未参加的考试:

SELECT s.code, s.name, p.course
FROM
  students s
  INNER JOIN
  programs p 
  ON (p.degree = s.degree)

这实际上是学生必须参加的考试列表

现在增加他们参加的考试,并为没有参加的考试留空:

SELECT s.code, s.name, p.course, e.course
FROM
  students s
  INNER JOIN
  programs p 
  ON (p.degree = s.degree)

  LEFT OUTER JOIN
  exams e
  ON e.student = s.code AND e.course = p.course

结果如下:

Code   | Name | p.Course | e.Course
stu001 | John | Calc A   | Calc A
stu001 | John | Calc B   | Calc B
stu002 | Doe  | Calc A   | <null>
stu002 | Doe  | Calc B   | <null>

现在将其简化为仅参加每门课程考试的学生的列表。我们可以通过检查COUNT(e.course)是否与COUNT(p.course)相同来完成此操作,因为COUNT()不计算NULL,因此e.course中出现的任何null(无检查)都会减少计数,与计算p.course的整体出现次数相比(我也可以使用count(*)):

SELECT s.code, s.name
FROM
  students s
  INNER JOIN
  programs p 
  ON (p.degree = s.degree)

  LEFT OUTER JOIN
  exams e
  ON e.student = s.code AND e.course = p.course

GROUP BY s.code, s.name
HAVING COUNT(p.course) = COUNT(e.course)

John的COUNT(p.Course)为2,COUNT(e.course)也为2,因此他显示(仅一次,因为他被分组了。Doe的COUNT(p.course)为2,但COUNT(e。当然)是0,因为所有值均为空,并且2!= 0,所以他是隐藏的