2015-04-22 70 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岁以下学生的数量”在 –

相关问题