Студенты, которые сдали тест по каждому курсу в своей степени - PullRequest
0 голосов
/ 29 октября 2018

Я пытался использовать подход «Не существует», чтобы выделить ответ, но я думаю, что зашел слишком глубоко. Я ограничен только тем, что использую как очень простые вещи для моего вступления в класс базы данных. Так что, в основном, только INNER JOIN, UNION и CASE и, возможно, несколько других вещей, но, вероятно, лучше всего предположить, что они абсолютно чистые. Нам пока не разрешено использовать коалесцирование.

Ответы [ 3 ]

0 голосов
/ 30 октября 2018

Мне нравится использовать агрегацию для этих вещей.

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, а также студент. В конце концов, студенты могут удвоить майор.

0 голосов
/ 30 октября 2018

Аналогично ответу Прели, я бы использовал левое соединение, чтобы выделить экзамены, которые не были сданы:

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 уменьшают count, по сравнению с подсчетом общего числа случаев 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)

УЧЕТ Джона (p.Course) будет равен 2, а COUNT (e.course) также будет 2, поэтому он показывает (только один раз, потому что он сгруппирован. COUNT у Доу (p.course) равен 2, но COUNT (e. Конечно) равен 0, потому что все значения равны нулю, а 2! = 0, поэтому он скрыт

0 голосов
/ 30 октября 2018

Не уверен, что это возможно только с 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

)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...