我认为在一个表中对合取和合取建模总是很不容易,并且会导致违反正常形式或无法预测需要多少个自我联接。我了解的是,您的前提条件通常可以表达为连词的替代形式。因此,以下内容:
Math AND English AND (Physics1 OR Physics2)
可能表示为:
(Math AND English AND Physics1) OR (Math AND English AND Physics2)
得出的结论是,您可能需要一个描述 先决条件集的 中间表。当 任何 一组成功时,课程就可用;而当一组中的 所有 科目都完成时,则该课程就成功。
因此结构可能如下所示:
Prerequisite:
+---------------+---------------+
| Id | Name |
|---------------|---------------| PrerequisiteSets:
| 1 | Maths | +---------------+---------------+
| 2 | English | | SetNumber | Prerequisite_FK
| 3 | Art | |---------------|---------------|
| 4 | Physics | | 1 | 1 |
| 5 | Psychology | | 1 | 2 |
+-------------------------------+ | 1 | 4 |
| 2 | 1 |
| 2 | 2 |
Course: | 2 | 5 |
+---------------+---------------+ +---------------v---------------+
| Id | Name |
|---------------|---------------|
| 1 | Course1 |
| 2 | Course2 |
| 3 | Course3 |
| 4 | Course4 |
| 5 | Course5 |
+---------------v---------------+
CoursePrerequisite:
+---------------+---------------+
| Course_FK | SetNumber |
|---------------|---------------|
| 5 | 1 |
| 5 | 2 |
+---------------v---------------+
示例5可以使用SetNumber 1(数学,英语,物理学)或SetNumber2(数学,英语,心理学)来满足。
不幸的是,现在为时已晚,无法为您提供确切的查询,但是如果您需要,我明天可以扩展我的答案。祝你好运!:-)
为了生成查询,我将从观察开始,当集合中的所有先决条件都是给定先决条件的子集时,将匹配该特定集合。这导致条件,集合中不同先决条件的数量必须与该集合中的给定集合中的前提条件的数量匹配。基本上(假设SetNumber- Prerequisite_FK是表中的唯一对):
select
SetNumber,
count(Prerequisite_FK) as NumberOfrequired,
sum(case when Prerequisite.Name in ('Math','English','Art') then 1 else 0 end)
as NumberOfMatching
from PrerequisiteSets
inner join Prerequisite on PrerequisiteSets.Prerequisite_FK = Prerequisite.ID
group by SetNumber
having
count(Prerequisite_FK)
=
sum(case when Prerequisite.Name in ('Math','English','Art') then 1 else 0 end)
现在获取最终课程归结为获取所有课程,在上面的查询结果中至少找到了一组编号。像这样开始(可以更好地表示并通过连接进行优化,但总体思路是相同的):
select Id, Name
from Course
where Id in
(select Course_FK from CoursePrerequisite
where SetNumber in
(
-- insert query from above (but only first column: SetNumber, skip the two latter)
) as MatchingSets
) as MatchingCourses