考虑一下像经济学这样的专业。假设学生需要选择“EC 101”或“EC 102”,但不一定要从该专业毕业。目前,我有两个这样的表:
课程:CourseID,CourseName
专业:MajorID,MajorName,RequiredCourseID
我如何能够获得有时主要要求的要求:要么选择课程A还是课程B,但不一定都在我的数据库设计中?
答案 0 :(得分:2)
专业有要求,课程可以填写要求。这种方式专业也可以分享共同的要求。
major requirementId
-----------------------
econ 1
econ 2
artOrSmth 2
requirementId coursename
------------------------------
1 econ101
1 econ102
2 math101
答案 1 :(得分:2)
你需要重构你的表,并引入一些额外的表:
课程:CourseID,CourseName
专业:MajorID,MajorName
MajorRequirements:MajorID,ReqId
要求:ReqId,ReqCount
RequiredCourseOptions:ReqId,CourseID
从问题:
经济学(EC001):假设学生需要选择“EC 101”或“EC 102”,但不一定要从该专业毕业。
其他要求:
此外,EC001专业的学生必须参加EC 200,EC 201,EC 202的所有三门课程。
政治经济学(EC002):与经济学一样,学生需要采用“EC 101”或“EC 102”,但不一定都是。此外,EC002专业的学生必须参加EC 200,EC 201,EC 202三门课程中的任何两门课程。(并且,可能还有其他未在此讨论过的课程。)
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门必修课程;有三门课程(EC 200,EC 201,EC 202),所以学生必须全部三门课程。
同样,在政治经济学(EC002)专业的人必须满足其专业的所有要求,这意味着必须满足MajorRequirments R01和R03。和以前一样,为了满足R01,学生必须从可用选项(EC 101或EC 102)中选择1门必修课程。为了满足R03,学生必须从可用选项中选修2门必修课;有三门课程(EC 200,EC 201,EC 202),学生必须至少选修三门课程。
显然,这可以用于从任何一组中要求任何N个M课程。如果一个专业M需要特定的课程C,那么MajorRequirements表包含一个ReqID R,用于主要M,ReqCount为1,RequiredCourseOptions记录R和C.R02所需的三个课程可以分为三个单独的要求,不同的ReqID值和每个ReqCount为1。但是,我希望通过R03显示3个课程中的2个的灵活性,并且对称性表明ReqID R02与ReqCount 3在某些方面更好。
哪些学生有资格毕业?
假设学生表包含StudentID,Name和MajorID(以及其他列,如出生日期,注册日期等),以及另一个表,StudentPassedCourses,其中包含StudentID和CourseID(以及通过日期和通过等级,等等)。只有学生通过课程后,参赛作品才会出现在StudentPassedCourses中。
然后,有资格毕业的学生是那些满足其专业要求的学生。
让我们使用 TDQD - 测试驱动的查询设计 逐步构建查询。
SELECT MajorID, COUNT(ReqID) AS CountReqs
FROM MajorRequirements
GROUP BY MajorID
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
(这是一个非常重要的步骤;可能需要分解为单独的步骤。)
这列出学生和要求ID,其中学生通过给定的ReqID计数至少是专业要求的通过次数。
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
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
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!