有没有办法与 table 的某些行进行比较?
Is there a way to compare with certain rows of a table?
这些是我的问题的相关表格
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 |
+-----------+--------+
为了找到学生 (enrolls.matric) 能够修读的所有模块 (prereqs.code),我使用了以下查询
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';
第二个子查询(UNION 之后)处理所有没有先决条件的模块,第三个子查询(EXCEPT 之后)删除学生 (A0000001A) 已经学习的所有模块。
当 运行 此查询时,CS3102 显示为可供学生选修的模块,情况不应如此,因为他只选修了 CS2030 而不是 CS2040。为了能够参加 CS3102,学生需要参加 both CS2030 和 CS2040。我不确定如何使用 SQL 强制执行此约束。我需要使用 PostgreSQL.
目前,我的查询似乎显示一个模块只要满足 一个 的先决条件就可以使用。我不确定如何修改我的查询以确保仅在 所有 满足其先决条件时才显示模块。
当前输出:
+--------+
| code |
+--------+
| CS2040 |
| CS3102 |
| IS2101 |
+--------+
期望的输出:
+--------+
| code |
+--------+
| CS2040 |
| IS2101 |
+--------+
这是一种使用 not exists
和 left join
的方法:
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
s 带来了先决条件和相应的注册,having
子句确保它们都得到满足。
我相信您可以使用一种双重否定来代替查询的第一部分和第二部分。像这样
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'
)
)
这些是我的问题的相关表格
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 |
+-----------+--------+
为了找到学生 (enrolls.matric) 能够修读的所有模块 (prereqs.code),我使用了以下查询
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';
第二个子查询(UNION 之后)处理所有没有先决条件的模块,第三个子查询(EXCEPT 之后)删除学生 (A0000001A) 已经学习的所有模块。
当 运行 此查询时,CS3102 显示为可供学生选修的模块,情况不应如此,因为他只选修了 CS2030 而不是 CS2040。为了能够参加 CS3102,学生需要参加 both CS2030 和 CS2040。我不确定如何使用 SQL 强制执行此约束。我需要使用 PostgreSQL.
目前,我的查询似乎显示一个模块只要满足 一个 的先决条件就可以使用。我不确定如何修改我的查询以确保仅在 所有 满足其先决条件时才显示模块。
当前输出:
+--------+
| code |
+--------+
| CS2040 |
| CS3102 |
| IS2101 |
+--------+
期望的输出:
+--------+
| code |
+--------+
| CS2040 |
| IS2101 |
+--------+
这是一种使用 not exists
和 left join
的方法:
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
s 带来了先决条件和相应的注册,having
子句确保它们都得到满足。
我相信您可以使用一种双重否定来代替查询的第一部分和第二部分。像这样
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'
)
)