2012-07-12 75 views
4

我想創建,我需要參加3個表SQL:INNER JOIN + NOT EXIST

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 

SQL語句科目

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) 

任何想法?

+2

做得好格式化表格,sqlfiddle進口他們漂亮。 – 2012-07-12 15:44:39

回答

4
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

+0

如果學生未註冊至少一個主題,則此功能無效 – Madman 2012-07-12 15:36:46

+0

如果EnrollStudent爲空,用戶ID記錄是否仍顯示? – abramlimpin 2012-07-12 15:40:03

+0

@Madman是的,你是對的。我編輯它,這應該做的伎倆。 – 2012-07-12 15:42:56

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

+0

已添加SQL Fiddle示例 – RedFilter 2012-07-12 16:50:22

1

它看起來像你正試圖資格在第一年所有學生在所有需要的第一年課程沒有招收誰,因此希望獲得唯一的學生2和3。您的數據的每個人一個yearID的團體,但我懷疑你實際上有多年的數據,你明確地關注第一年的那些學生,以及那些也與第一年需求相關的主題。

第一個查詢(YrSubjects)結果將預先聚合有問題的單年份的類的數量,因此它不必爲每個學生重複執行此操作。只需要一次......將其作爲未分配JOIN加入到查詢的其餘部分將是笛卡兒,但每個人一個記錄,無論如何不會有重複。

接下來是其餘的表/連接。獲取註冊僅與第1年相關的科目的學生。where子句明確限制僅限於那些「第1年」的學生。

最後的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