SQL 以多对多关系查找不属于特定集合的所有元素

SQL Finding all elements which does not belong to a particular set, in many to many relation

我对这个任务有疑问:

Given are the relations

Students: ST (S#, SNAME)

Lecture: L (L#, LNAME, ECTS)

Who attends what: LS (L#, S#)

Find students (S# and SNAME) who do not attend any lecture having more than 4 ECTS

我知道我可以通过检查给定学生的 ECTS 最大值是否大于 4 来做到这一点,但作为学习的一部分,我想以不同的方式进行。即我想使用子查询来做到这一点:

SELECT S.[S#], SNAME
FROM ST
INNER JOIN LS ON LS.[S#] = S.[S#]
WHERE LS.[L#] /* and here is a problem, I want a statement like "none of LS.[L#] exists in" */ (SELECT [L#] FROM L WHERE ECTS > 4)

我的想法是 (SELECT [L#] FROM L WHERE ECTS > 4) 将 return 所有 ECTS 大于 4 的讲座,然后我只需要检查此集合中是否存在其中一个通过 LS table 分配给 Student,然后跳过它。

我知道存在 ALL 和 ANY 等运算符,但它似乎在任何配置下都不起作用。

我试过例如 WHERE NOT LS.[L#] = ANY (SELECT [L#] FROM L WHERE ECTS > 4),但由于它根据 LS.[L#] 单独运行,它只是 return 让我的学生至少有一个 ECTS <= 4 的讲座。

我发现 WHERE LS.[L#] = ANY (SELECT [L#] FROM L WHERE ECTS > 4) 完全否定了我想要的集合 - 天真地我认为不会反转这个集合 - 但显然不会 - 在这种情况下我想要的是 ALL STUDENTS - WHERE LS.[L#] = ANY (SELECT [L#] FROM L WHERE ECTS > 4).

这个问题有这种方式的巧妙解决方案吗?

您可以按如下方式使用not exists

SELECT S.[S#], SNAME
  FROM ST
  INNER JOIN LS ON LS.[S#] = S.[S#]
WHERE not exists
      (select 1 from L
        Where L.[L#] = LS.[L#]
          AND L.ECTS > 4)

使用我们将命名为“Temp”的子查询,其中包含 参加 超过 4 ECTS 的讲座的学生列表,我们可以 select 从使用 LEFT JOIN 不在该列表中的学生:

SELECT
  ST.[S#],
  ST.SNAME
FROM ST
LEFT JOIN
  (SELECT LS.[S#]
    FROM SL
    JOIN L
    ON SL.[L#] = L.[L#]
    WHERE L.ECTS > 4
  ) AS Temp
ON ST.[S#] = Temp.[S#]
WHERE Temp.[S#] IS NULL

可以使用NOT EXISTS,但正确的逻辑是:

SELECT S.[S#], s.SNAME
FROM S
WHERE NOT EXISTS (SELECT 1
                  FROM LS JOIN
                       L
                       ON L.[L#] = LS.[L#]
                  WHERE LS.[S#] = S.[S#] AND L.ECTS > 4
                 ) ;

也就是你要加入子查询