有没有办法与 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 existsleft 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 joins 带来了先决条件和相应的注册,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'
      )
)