2015-04-22 95 views
-3

我與表的數據庫:這是連接表來獲取數據的正確方法嗎?

Student(SID,Name,Surname,Age) 
Registration(StudentID,CourseID) 
Course(CID,Name,Cost) 

我想提取與學生的課程超過20個年輕下面的查詢做到這一點只有名字?

SELECT C.NAME 
FROM Course C 
INNER JOIN Registration 
INNER JOIN Student S 
WHERE CID = CourseID 
    AND SID = StudentID 
    AND Age < 20 
GROUP BY C.NAME 

我也想提取學生每門課程讓學生比20年輕的數量是否正確,如下辦呢?

SELECT count(S.NAME) 
    ,C.NAME 
FROM Student S 
INNER JOIN Course C 
INNER JOIN Registration 
WHERE Age < 20 
    AND CID = CourseID 
    AND SID = StudentID 
GROUP BY C.NAME 
+0

你用什麼db? Mysql還是SQL?有兩個sintax之間的區別 –

+1

@LelioFaieta你可以給我一個鏈接到'SQL'數據庫嗎?我很好奇它與MySQL的區別。 –

+0

@ Lelio - post被標記爲MySQL .... – MuppetGrinder

回答

0

您錯過了連接的ON部分,否則它只是一個CROSS JOIN。

你的第一個查詢應該是這樣的,如果你想學生的名字只是一個不同的列表:

SELECT DISTINCT C.NAME 
FROM Course C 
INNER JOIN Registration R ON C.CID = R.CourseID 
INNER JOIN Student S ON R.StudentID = S.SID 
WHERE Age < 20 

你的第二個查詢應該不是真的有C.Name的選擇,如果你想要得到的只是除非你想知道有多少學生擁有這個名字,否則算數。

SELECT count(*) 
FROM Student S 
INNER JOIN Registration R ON s.SID = R.StudentID 
INNER JOIN Course C ON c.CID = R.CourseID 
WHERE Age < 20 
GROUP BY C.NAME 
+0

確實,第一個查詢不需要GROUP BY,但我認爲OP實際上是在尋找DISTINCT,因爲JOIN with Registration很可能會產生重複的課程名稱。因此,我建議您調整您的答案,並在第一個查詢中包含DISTINCT。 –

+0

@RaduGheorghiu啊這是一個很好的觀點,因爲它可能是多對多的。 – SLin

+0

......內部連接只是一個過濾的交叉連接。 OP中的查詢提供了所需的結果,只是以一種混合了隱式和顯式連接語法的稍微奇怪的格式。 –

0

更正確,你應該將的加盟條件,通過包括他們on條款,而不是where在加入語句本身。雖然在這種情況下結果可能不會改變,但如果你開始包括outer joins,你會遇到困難。

SELECT count(S.NAME) 
    ,C.NAME 
FROM Student S 
INNER JOIN Registration R 
    ON s.SID = R.StudentID 
INNER JOIN Course C 
    ON c.CID = R.CourseID 
WHERE Age < 20 
GROUP BY C.NAME 

這裏有一個小提琴顯示行動吧:http://sqlfiddle.com/#!9/c3b8f/1

你的第一個查詢也將產生你想要的結果,但同樣,你應該將連接謂詞的加入本身。此外,您不需要執行分組只是爲了獲取不同的值,mysql有一個稱爲distinct的表達式。因此改寫,第一個查詢看起來像:

SELECT DISTINCT C.NAME 
FROM Student S 
INNER JOIN Registration R 
    ON s.SID = R.StudentID 
INNER JOIN Course C 
    ON c.CID = R.CourseID 
WHERE Age < 20. 

再次,結果都是一樣的,你有什麼了,不過它更容易「讀」,將讓你受益無窮,當你移動到其他查詢。就目前而言,您已經混合了隱式和顯式連接語法。

這撥弄同時演示了查詢:http://sqlfiddle.com/#!9/c3b8f/4

編輯

我可能誤解了你原來的問題 - 如果你想19歲以下參加的課程與至少一個學生的學生總數,你可以使用這樣的查詢:

select name, count(*) 
    from course c 
    inner join registration r 
     on c.cid = r.courseid 
    where exists (
    select 1 
     from course cc 
     inner join registration r 
      on cc.cid = r.courseid 
     inner join student s 
      on s.sid = r.studentid 
     where cc.cid = c.cid 
     group by cc.cid 
     having min(s.age) < 20 
    ) 
    group by name; 

再次更新小提琴這裏:http://sqlfiddle.com/#!9/c3b8f/17

0

首先加入這些表,然後按課程的PK(CID),添加HAVING條件來篩選其中有學生20餘

年輕過程然後使用Course表連接的結果獲取課程中學生的課程名稱和人數。

SELECT 
    T1.Name, 
    T2.StudentCount 
FROM 
    Course T1 
INNER JOIN (
    SELECT 
     c.CID, 
     COUNT(s.SID) AS StudentCount 
    FROM 
     Course c 
    LEFT JOIN Registration r ON c.CID = r.CourseID 
    LEFT JOIN Student s ON s.SID = r.StudentID 
    GROUP BY c.CID 
    HAVING COUNT(IF(s.Age < 20, 1, NULL)) > 0  
) T2 ON T1.CID = T2.CID 
+0

你可能想要刪除你所有的語法錯誤。 –

+0

@pala_ Thx,固定。 – xdazz

+0

現在真正的問題是,操作真的意味着「所有學生的數量」或者「所有20歲以下學生的數量」在 –

相關問題