问题描述
前天看到群里有人问了一个关于数据库查询的问题,问题大概如下:
基本表是s(学生表),c(课程表),sc(学生选课表),怎么查询选修了所有2学分课程的学生姓名。
问题解决
代数解决
此类问题应该用除法解决,用sc表取除以所有2学分的课程表,得到选修了所有2学分的学生学号,然后根据学生学号查询学生姓名。
表达式为:∏name(sc ÷ϭcredit=2(c)⋈S)
该表达式有选择、除法、投影和连接操作。其中最主要的就是除法运算,这里就说说我对除法运算的理解。
设关系R除以关系S的结果为关系T,则T包含所有在R但不在S中的属性及其值,且T的元祖与S的元祖的所有组合都在R中,这里的除法可以变相理解为整除。只有被除数含有除数的全部,才可以纳进结果集中。如图所示,只有修了数学和语文才可以被整除,然后得出选修了所有课程的学生。
所以解答问题的思路,就是要先查询出课程号为2的所有课程,然后用课程表除以该结果,就得出了选修所有2学分课程的学号,然后与学生表连接,最后按姓名投影即可。
SQL语句解决
我这里采用了not exist 方法来解决,注意该子查询不返回任何结果集,只返回true.false.
思路是上述问题可以转述为查询出没有不选择全部2学分课程的学生。
select name
from s
where not exist(
select *
from c
where credit = 2 and not exist (
select *
from sc
where sc.cno=c.cno and sc.sno=s.sno
)
)