web-dev-qa-db-ja.com

少なくともid = 1の学生が失敗したすべてのコースで失敗した学生を選択するにはどうすればよいですか?

私は次の表を持っています:

STUDENT (student_id, first_name, last_name, birth_date, year , domain)

PROFESSOR (professor_id, first_name, last_name, birth_date, hire_date, title, salary)

COURSE (course_id, course_name, professor_id)

GRADE (student_id, course_id, grade, date_of_exam)

少なくともid = 1の学生が失敗したすべてのコースで失敗した学生を表示する必要があります。

私が試したこと:

SELECT
s.student_id,
s.first_name,
s.last_name,
n.grade,
n.course_id
FROM
    student s
    JOIN grade n ON n.student_id = s.student_id
WHERE
    n.grade <= 4;

...これにより、失敗したすべての学生が取得されますが、少なくともid = 1の学生が失敗したすべてのコースで失敗したすべての学生にこれから移動する方法がわかりません。誰かが私を正しい方向に向けることができれば、私は感謝するでしょう!

追加の詳細

例:id = 1の学生がids = 2,3のコースで失敗した場合。また、ids = 2,3のコースで失敗した他の2人の学生(学生1など)がいて、他のコースでも失敗する可能性があるので、これら2人の学生を表示します。

1
Eduard Valentin

これがあなたの望む結果を得る一つの方法です

SELECT *
FROM   STUDENT S
WHERE  NOT EXISTS (SELECT g1.course_id
                   FROM   GRADE g1
                   WHERE  g1.student_id = 1
                          AND g1.grade <= 4
                   MINUS
                   SELECT g2.course_id
                   FROM   GRADE g2
                   WHERE  g2.student_id = S.student_id
                          AND g2.grade <= 4) 

学生ごとに、MINUSで、student_id = 1が失敗したコースがあり、フォーカスされている学生の失敗したコースのセットに含まれていないかどうかを確認します。

そのようなコースがない場合は、NOT EXISTSがtrueと評価され、学生が返されます。

少なくとも自分と同じ数のコースに明らかに失敗したため、student_id = 1が返されます。そのため、それを除外することをお勧めします。

1
Martin Smith

私がそれを正しく理解した場合、学生が合格し、ID1の学生が失敗したコースが存在しない学生が必要です。

SELECT student_id
FROM student s
WHERE student_id <> 1
  AND NOT EXISTS (
    SELECT 1 
    FROM GRADE g1
    JOIN GRADE g2
        ON g1.course_id = g2.course_id
    WHERE g1.student_id = 1
      AND g1.grade <= 4
      AND g2.student_id = s.student_id
      AND g2.grade > 4
);

私はgrade > 4は合格を意味します。

1
Lennart

これにより、同じクラスに失敗したすべての生徒がひとまとめになります。

    with failboat as (select s.student_ID, c.course_id, g.Grade, 
    rank() over (partition by s.student_id order by date_of_exam) as failcount
    from STUDENT s
    inner join GRADE  on s.student_ID = g.student_ID
    inner join Course c on g.course_ID = c.course_ID
    where g.grade <=4)

    select f1.*, f2.*
    from failboat f1
    inner join failboat f2 on f1.courseID = f2.CourseID
0
James