sql如何为noob编写复杂的查询?

时间:2012-10-31 19:59:39

标签: sql database

这是我的表格

 Student (sname, sid, gpa, level, deptno) 
 Course (cno, cname, deptno, units) 
 Dept (dname, deptno) 
 Takes (sid, cno) 

编写一个SQL查询,返回已经学过的学生的姓名(即snames) 在他们的部门以外的课程比在他们的部门内更多。你可以 假设数据库中的所有学生都在其所在部门内至少学过一门课程。

我不是在寻找这个问题的任何解决方案,但仍欢迎任何答案。 但我希望人们可以告诉我如何生成编写像这样的复杂查询的步骤..

我的回答是

 Select S.sname
 From Student S, Course C, Dept D, Takes T
 Where T.cno=C.cno and D.deptno=C.deptno and S.sid = T.sid
 Having COUNT(S.deptno=C.deptno) > COUNT( S.deptno != C.deptno)

我不确定以这种方式HAVING之后我可以使用计数。 感谢

3 个答案:

答案 0 :(得分:2)

我经常使用中等复杂的SQL查询,尽管从未使用过DB / SQL类,并且发现生成查询的最佳方法是一次处理一个。例如,首先要获得学生名单。然后,他们在dept内外的类数量,最后,比较查询中的两个值,并返回您需要的最终结果集。,

tl;博士:宝贝步骤

答案 1 :(得分:2)

有人认为这是hw,但这是标准解决方案:

 SELECT S.sname from Student S
 WHERE (SELECT COUNT (*) 
 FROM Takes T, Course C
 WHERE S.sid = T.sid AND T.cno = C.cno AND C.deptno = S.deptno)
 < (SELECT COUNT(*)
 FROM Takes T2, Course C2
 WHERE S.sid = T2.sid AND T2.cno = C2.cno AND C2.deptno != S.deptno)

答案 2 :(得分:1)

你的第一次尝试,更正了:

 SELECT S.sname
 FROM Student S, Course C, Dept D, Takes T
 WHERE T.cno = C.cno AND D.deptno = C.deptno AND S.sid = T.sid
 GROUP BY S.sid
 HAVING COUNT(CASE WHEN S.deptno =  C.deptno THEN 1 ELSE NULL END) 
      < COUNT(CASE WHEN S.deptno <> C.deptno THEN 1 ELSE NULL END) ;

并转换为SQL-92语法:

 SELECT S.sname
 FROM Student S 
   JOIN Takes T   ON S.sid = T.sid
   JOIN Course C  ON T.cno = C.cno
   JOIN Dept D    ON D.deptno = C.deptno
 GROUP BY S.sid        
        , S.sname                  --- this is not needed in SQL-2003
                                   --- but still required by most DBMS     
 HAVING 
        COUNT(CASE WHEN S.deptno =  C.deptno THEN 1 END) 
      < COUNT(CASE WHEN S.deptno <> C.deptno THEN 1 END) ;

                                   --- the ELSE NULL is not needed either
                                   --- it's the implied default