スキーマ設計
テーブルをリファクタリングし、追加のテーブルをいくつか導入する必要があります。
コース: CourseID、CourseName
Majors: MajorID、MajorName
MajorRequirements: MajorID、ReqId
要件: ReqId、ReqCount
RequiredCourseOptions: ReqId、CourseID
サンプルデータ
質問から:
経済学 (EC001): 学生がその専攻を卒業するために「EC 101」または「EC 102」のいずれかを取得する必要があるが、必ずしも両方を取得する必要はないとします。
追加要件:
また、EC001 を専攻する学生は、EC 200、EC 201、EC 202 の 3 つのコースをすべて受講する必要があります。
政治経済学 (EC002): 経済学と同様に、学生は「EC 101」または「EC 102」のいずれかを受験する必要がありますが、必ずしも両方を受験する必要はありません。また、EC002 を専攻する学生は、EC 200、EC 201、EC 202 の 3 つのコースのうち任意の 2 つを受講する必要があります。
コース
Course ID Name
EC 101 Economics 101
EC 102 Economics 102
EC 200 Economics 200
EC 201 Economics 201
EC 202 Economics 202
メジャー
Major ID Name
EC001 Economics
EC002 Political Economy
主な要件
MajorID ReqID
EC001 R01
EC001 R02
EC002 R01
EC002 R03
要件
ReqID ReqCount
R01 1
R02 3
R03 2
必須コースオプション
ReqID CourseID
1 EC 101
1 EC 102
2 EC 200
2 EC 201
2 EC 202
3 EC 200
3 EC 201
3 EC 202
解釈
経済学を専攻する人 (EC001) は、専攻のすべての要件を満たす必要があります。つまり、MajorRequirements R01 および R02 を満たす必要があります。R01を満たすには、学生は利用可能なオプションから1つの必須コースを受講している必要があります。必要なコース オプションは EC 101 と EC 102 です。どちらかで十分でしょう。R02を満たすには、学生は利用可能なオプションから3つの必須コースを受講している必要があります。3 つのコース (EC 200、EC 201、EC 202) があるため、学生は 3 つすべてを受講する必要があります。
同様に、政治経済学 (EC002) を専攻する人は、その専攻のすべての要件を満たす必要があります。つまり、MajorRequirments R01 および R03 を満たす必要があります。以前と同様に、R01 を満たすには、学生は利用可能なオプション (EC 101 または EC 102) から 1 つの必須コースを受講している必要があります。R03を満たすには、学生は利用可能なオプションから2つの必須コースを受講している必要があります。3 つのコース (EC 200、EC 201、EC 202) があり、学生は 3 つのうち少なくとも 2 つを受講している必要があります。
明らかに、これを使用して、任意のセットから N 個の M 個のコースを要求できます。メジャー M が特定のコース C を必要とする場合、MajorRequirements テーブルには、ReqCount が 1 のメジャー M の ReqID R と、R および C を記録する RequiredCourseOptions が含まれます。 ReqID 値とそれぞれ 1 の ReqCount。ただし、R03 を使用した 3 つのコースのうち 2 つのコースの柔軟性を示したかったのです。対称性は、ReqCount 3 を使用した ReqID R02 の方がいくつかの点で優れていることを示唆しています。
卒業資格者の選抜
どのような学生が卒業する資格がありますか?
列 StudentID、Name、MajorID (および生年月日、入学日などの他の列) を持つ Student のテーブルと、列 StudentID および CourseID (および合格日と合格成績など) を持つ別のテーブル StudentPassedCourses を想定します。エントリは、学生がコースに合格した場合にのみ StudentPassedCourses に表示されます。
そして、卒業資格は、専攻の各要件を満たした者です。
TDQD — Test Driven Query Designを使用して、クエリを段階的に作成しましょう。
Q1:専攻の卒業要件数
SELECT MajorID, COUNT(ReqID) AS CountReqs
FROM MajorRequirements
GROUP BY MajorID
Q2: 学生による要件の合格数
SELECT s.StudentID, m.ReqID, COUNT(*) AS PassCount
FROM StudentPassedCourses AS p
JOIN Students AS s ON p.StudentID = s.StudentID
JOIN MajorRequirements AS m ON s.MajorID = m.MajorID
GROUP BY s.StudentID, m.ReqID
(これはかなり大きなステップです。別のステップに分割する必要があるかもしれません。)
Q3:一定の条件を満たす学生
これは、特定の ReqID の学生の合格数が少なくとも専攻で必要な合格数である学生と要件 ID をリストします。
SELECT p.StudentID, p.ReqID
FROM (SELECT s.StudentID, m.ReqID, COUNT(*) AS PassCount -- Q2
FROM StudentPassedCourses AS p
JOIN Students AS s ON p.StudentID = s.StudentID
JOIN MajorRequirements AS m ON s.MajorID = m.MajorID
GROUP BY s.StudentID, m.ReqID
) AS p
JOIN MajorRequirements AS m ON p.ReqID = m.ReqID
WHERE p.PassCount >= m.ReqCount
Q4: 各学生の要件数を集計する
SELECT r.StudentID, COUNT(*) AS ReqsPassed
FROM (SELECT p.StudentID, p.ReqID -- Q3
FROM (SELECT s.StudentID, m.ReqID, COUNT(*) AS PassCount -- Q2
FROM StudentPassedCourses AS p
JOIN Students AS s ON p.StudentID = s.StudentID
JOIN MajorRequirements AS m ON s.MajorID = m.MajorID
GROUP BY s.StudentID, m.ReqID
) AS p
JOIN MajorRequirements AS m ON p.ReqID = m.ReqID
WHERE p.PassCount >= m.ReqCount
) AS r
GROUP BY r.StudentID
Q5:専攻に合格した学生
SELECT s.StudentID, s.Name, s.MajorID, m.Name Major
FROM Students AS s
JOIN Majors AS m ON m.MajorID = s.MajorID
JOIN (SELECT r.StudentID, COUNT(*) AS ReqsPassed -- Q4
FROM (SELECT p.StudentID, p.ReqID -- Q3
FROM (SELECT s.StudentID, m.ReqID, COUNT(*) AS PassCount -- Q2
FROM StudentPassedCourses AS p
JOIN Students AS s ON p.StudentID = s.StudentID
JOIN MajorRequirements AS m ON s.MajorID = m.MajorID
GROUP BY s.StudentID, m.ReqID
) AS p
JOIN MajorRequirements AS m ON p.ReqID = m.ReqID
WHERE p.PassCount >= m.ReqCount
) AS r
GROUP BY r.StudentID
) AS c ON c.StudentID = s.StudentID
JOIN (SELECT MajorID, COUNT(ReqID) AS CountReqs -- Q1
FROM MajorRequirements
GROUP BY MajorID
) AS r ON r.MajorID = s.MajorID
WHERE c.ReqsPassed >= r.CountReqs
警告: テストされていない SQL!