【问题标题】:SQL question: Show me students who have NOT taken a certain course?SQL 问题:告诉我没有上过某门课程的学生?
【发布时间】:2010-07-08 15:07:18
【问题描述】:

所以我有这些表:

学生: 学生证 - 名字 - 姓氏 - 电子邮件

课程: 目录 ID - 课程名称 - 描述

条款: 学期 ID - 开始日期 - 结束日期

课程实例: CourseInstance ID - 目录 ID - 学期 ID

学生课程: StudentCourse ID - CourseInstance ID - Student ID - 添加到数据库的日期

这样可以轻松查看哪些学生参加了哪些课程。我不确定如何找出哪些学生没有上过特定的课程。

做这样的事情:

WHERE ((CourseInstances.CatalogLookup)<>504)

只会给我一个不等于目录号 504 的学生所学课程的列表,如下所示:

塔拉 - 501

塔拉 - 502

塔拉 - 505

约翰 - 503

例如,我选择了 504。因此我不希望我出现在此列表中。上面的 SQL 只会显示我所有不是 504 的课程,但不会将我排除在列表之外。

有什么想法吗?这可能吗?

【问题讨论】:

    标签: sql ms-access


    【解决方案1】:

    我更喜欢这种语法而不是外连接,IMO 更容易阅读:

    select * 
    from STUDENTS 
    where StudentID not in 
    (
        select StudentID 
        from STUDENTCOURSES s 
        inner join COURSEINSTANCES c on s.CourseInstanceID  = c.CourseInstanceID 
        where c.CatalogID = 504
    )
    

    在嵌套查询中,您选择所有参加过 504 课程的学生的 StudentID。

    然后,您选择所有 StudentID 未包含在嵌套查询中的学生。

    编辑:
    正如 ChrisJ 已经说过的,c 和 s 是表名的别名。
    没有它们,查询将如下所示:

    select * 
    from STUDENTS 
    where StudentID not in 
    (
        select StudentID 
        from STUDENTCOURSES 
        inner join COURSEINSTANCES on STUDENTCOURSES.CourseInstanceID = COURSEINSTANCES.CourseInstanceID 
        where CatalogID = 504
    )
    

    我总是使用别名,因为:
    a) 我懒得更频繁地输入表名。
    b)在我看来,它更容易阅读,尤其是当您连接具有长名称的表时。

    【讨论】:

    • 嗯。我理解这个概念,但不理解执行。你能解释一下 c 和 s 的含义吗?
    • 它们是表别名。它们只是您为表格命名的小名称,因此您以后不必再次输入整个名称。不过,他们真的应该阅读 STUDENTCOURSES。
    • 我明白了!感谢您的帮助!
    • 并不是说 Jet/ACE 有时无法使用 NOT IN (SELECT ...) 标准两侧的索引。它统一使用带有普通 IN 的索引,但由于某种原因,有时它不能同时使用带有 NOT IN 的索引(而且我从来没有找到一个可预测的模式来预测它何时发生)。因此,我倾向于使用 OUTER JOIN 而不是 IN () 子句。但是,如果结果需要可编辑,您可能需要改用 IN 版本。
    【解决方案2】:

    试试这样的:

    SELECT * 
    FROM Users 
    WHERE UserID NOT IN
    ( SELECT UserID
      FROM 
        Users
      INNER JOIN
        ClassesTaken ON Users.UserID = ClassesTaken.UserID AND ClassesTaken.ClassNumber = 504)
    

    前几天我想到了另一种方式:

    SELECT * 
    FROM 
    Users
    LEFT OUTER JOIN ClassesTaken ON Users.UserID = ClassesTaken.UserID AND ClassesTaken.ClassNumber = 504
    WHERE ClassesTaken.UserID IS NULL
    

    【讨论】:

      【解决方案3】:

      你应该阅读outer joins

      【讨论】:

        【解决方案4】:
        SELECT * FROM students 
        WHERE studentId not in 
        (SELECT distinct studentID FROM studentCourses WHERE courseInstanceID = 504)
        

        【讨论】:

          【解决方案5】:

          Access中的三种主要方式

          • NOT IN(如果 NULL 有可能出现在子查询中,请小心排除它们)
          • OUTER JOIN 和过滤 NULL(可能需要添加 DISTINCT)
          • 不存在

          其他 RDBMS 也有 EXCEPTMINUS

          【讨论】:

          • OP 指定 MS Access,所以except / minus 不是选项。
          • @Frustrated - 是的,只是注意到我自己 :-)
          • FWIW MS Access 也有ANY 及其同义词SOME(和ALL,但不适用于这个问题)。
          【解决方案6】:

          家庭作业?使用集合运算符。

          选择所有学生 MINUS 选择任何参加过这门课程的学生...

          【讨论】:

          • 这不是家庭作业。这是工作 - 工作。您的回答有点像只是重申我的问题,我不知道如何使用它来解决它。
          • 没有。 MS Access 没有 MINUS 运算符。
          猜你喜欢
          • 2014-09-14
          • 2014-06-14
          • 2021-11-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-07-22
          相关资源
          最近更新 更多