这些是我的问题的相关表格
<samlp:LogoutRequest ...
为了找到学生(enrolls.matric)可以使用的所有模块(prereqs.code),我使用了以下查询
modules
+--------+
| code |
+--------+
| CS1010 |
| CS2030 |
| CS2040 |
| IS3103 |
| IS2101 |
| CS3102 |
+--------+
prereqs
+--------+--------+
| code | need |
+--------+--------+
| CS2030 | CS1010 |
| CS2040 | CS1010 |
| IS3103 | IS2101 |
| CS3102 | CS2030 |
| CS3102 | CS2040 |
+--------+--------+
enrolls
+-----------+--------+
| matric | code |
+-----------+--------+
| A0000001A | CS1010 |
| A0000001A | CS2030 |
+-----------+--------+
第二个子查询(在UNION之后)处理所有没有先决条件的模块,而第三个子查询(在EXCEPT之后)删除学生已经使用的所有模块(A0000001A)。
运行此查询时,CS3102会显示为可供学生采用的模块,但事实并非如此,因为他仅参加了CS2030,而没有参加CS2040。为了能够参加CS3102,学生需要同时参加两者 CS2030和CS2040。我不确定如何使用SQL强制执行此约束。我必须使用PostgreSQL。
当前,我的查询似乎显示只要满足其中的一个条件,就可以使用该模块。我不确定如何修改查询以确保仅在满足 all 的先决条件的情况下显示模块。
当前输出:
SELECT P.code
FROM enrolls E, prereqs P
WHERE E.matric = 'A0000001A'
AND P.need IN (SELECT code FROM enrolls)
UNION
SELECT M.code
FROM modules M, prereqs P
WHERE M.code NOT IN (SELECT code FROM prereqs)
EXCEPT
SELECT code
FROM enrolls
WHERE matric = 'A0000001A';
所需的输出:
+--------+
| code |
+--------+
| CS2040 |
| CS3102 |
| IS2101 |
+--------+
答案 0 :(得分:0)
这是使用not exists
和left join
s的一种方法:
select m.code
from modules m
left join prereqs pr on pr.code = m.code
left join enrolls e on e.code = pr.need and e.matric = 'A0000001A'
where not exists (select 1 from enrolls e where e.code = m.code and e.matric = 'A0000001A')
group by m.code
having count(pr.code) = count(e.code)
not exists
条件会过滤掉给定矩阵已经使用的模块。另一方面,left join
带来了先决条件和相应的注册,而having
子句确保它们都得到满足。
答案 1 :(得分:0)
我相信您可以进行某种双重否定来代替查询的第一部分和第二部分。像这样
SELECT P.code
FROM prereqs P
WHERE not exists (
select 1 from prereqs p2 where p2.code=P.code and p2.code not in (
select code from enrolls E where E.matric = 'A0000001A'
)
)