问题描述
前天看到群里有人问了一个关于数据库查询的问题,问题大概如下:
基本表是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
-
)
-
)