首页 > 解决方案 > SQL 在多对多关系中查找不属于特定集合的所有元素

问题描述

我对这个任务有疑问:

给定的是关系

学生:ST(S#,SNAME)

讲座:L(L#,LNAME,ECTS)

谁参加什么:LS (L#, S#)

查找不参加任何课程且学分超过 4 个的学生(S# 和 SNAME)

我知道我可以通过检查给定学生的 ECTS 的 MAX 值是否大于 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)返回所有 ECTS 大于 4 的 Lectures,然后我只需要检查这组中是否存在通过 LS 表分配给 Student 的 Lectures 之一,然后跳过它。

我知道存在像 ALL 和 ANY 这样的运算符,但它似乎不适用于任何配置。

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

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

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

标签: sqlmany-to-many

解决方案


您可以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)

推荐阅读