SQL:INNER JOIN + NOT EXIST

时间:2012-07-12 15:26:58

标签: sql inner-join not-exists

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

EnrollStudents

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)

有什么想法吗?

3 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

看起来你正试图让所有第一年没有报名参加所有第一年必修课程的学生取得资格,因此只想找到学生2和3.你的数据中包含一个年级ID的所有人,但我怀疑你实际上有多年的数据,你明确关心的是第一年的学生,以及那些与第一年要求相关的学科。

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

接下来是其余表/联接。让参加仅与第1年相关的科目的学生参加。哪里的条款明确限制为仅限于那些&#34;第一年&#34;生。

最终的HAVING条款适用的入学人数少于第一年要求的总科目数。使用此查询,您不会被修复&#34;到你想要的某些硬编码的科目......

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