【问题标题】:SQL: INNER JOIN + NOT EXISTSQL:内部联接 + 不存在
【发布时间】:2012-07-12 09:41:16
【问题描述】:

我正在尝试创建一个需要加入 3 个表的 SQL 语句

注册学生

EnrollID     UserID     SubjID
1            1          1
2            1          2
3            1          3
4            3          1
5            7          2

学生

StudentID     UserID     YearID
1             1          1
2             3          1
3             7          1

主题

SubjID     SubjCode     YearID
1          English      1
2          Math         1
3          Science      1

输出应该是……

UserID
2
3

因为User 1已经注册了所有科目,而User 3User 7仍然显示,因为有些科目还没有注册。

我有以下 SQL 语句没有运气:

SELECT Students.UserID 
FROM Students 
WHERE Students.YearID = 1 
    AND Students.UserID NOT IN (SELECT EnrollStudents.UserID 
                                FROM EnrollStudents)

有什么想法吗?

【问题讨论】:

  • 很好地格式化表格,sqlfiddle 漂亮地导入了它们。

标签: sql inner-join not-exists


【解决方案1】:

您似乎正在尝试让所有第一年未参加所有第一年必修课程的学生获得资格,因此只希望获得学生 2 和 3。您的数据包含单个 yearID 组中的每个人,但我怀疑您实际上拥有跨越多年的数据,并且您明确关注的是第一年的那些学生,以及那些也与第一年要求相关的科目。

第一个查询 (YrSubjects) 结果将预先汇总相关一年的班级数量,因此不必为每个学生重复执行此操作。只有一次...作为未分配的 JOIN 到查询的其余部分将是笛卡尔,但每人一条记录,无论如何都不会重复。

接下来是其余的表/连接。获取只与第一年相关的科目注册的学生。where 子句明确限制为仅限于那些“第一年”学生。

最后的 HAVING 子句应用的入学人数少于第一年要求的总科目数。使用此查询,您不会“固定”到您期望的某个硬编码数量的主题中......

SELECT 
      S.StudentID 
   FROM 
      ( select count(*) as YrClasses 
           from 
              Subjects 
           where YearID = 1 ) YrSubjects,
      Students S
         JOIN EnrollStudents ES
            on S.UserID = ES.UserID
            JOIN Subjects S
               ON ES.SubjID = S.SubjID
              AND S.YearID = 1
   WHERE 
      S.YearID = 1 
   HAVING
      count(*) < YrSubjects.YrClasses

【讨论】:

    【解决方案2】:
    select s.UserID
    from Students s
    left outer join (
        select UserID
        from EnrollStudents
        group by UserID
        having count(distinct SubjID) = 3
    ) a on s.UserID = a.UserID
    where a.UserID is null 
        and s.YearID = 1
    

    SQL Fiddle Example

    【讨论】:

      【解决方案3】:
      SELECT s.UserID
      FROM Students AS s
      LEFT OUTER JOIN EnrollStudents AS es ON s.UserID = es.UserID
      GROUP BY s.UserID
      HAVING COUNT(DISTINCT(es.SubjID)) < (SELECT COUNT(*) FROM Subjects)
      

      ...等一下。我认为您在示例输出和EnrollStudents 表中混淆了“StudentID”和“UserID”。

      http://sqlfiddle.com/#!3/61618/1

      【讨论】:

      • 如果学生没有注册至少一门科目,这将不起作用
      • 如果 EnrollStudent 为空,UserID 记录还会显示吗?
      • @Madman 是的,你是对的。我编辑了它,这应该可以解决问题。
      • @eibhrum 是的,正如您在 sqlfiddle 中看到的那样,用户 7 即将到来,他们没有注册任何内容
      • @eibhrum 这不是我的意思。 Students 表中有用户 ID (1,3,7),但在 EnrollStudents 中,您引用的是用户 ID (1,2,3)。我认为您的意思是 StudentID。
      猜你喜欢
      • 1970-01-01
      • 2012-01-28
      • 1970-01-01
      • 1970-01-01
      • 2011-12-23
      • 2018-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多