一、SQL语言查询选修了全部课程的学生的学号和姓名。
两种解决途径:
第一种:
我们可以表示为在SC表中某个学生选修的课程数等于C表中课程总数。相应的SQL语言如下:
select S#,SNAME from S where S# in (select S# from SC group by S# --根据Sno分组,统计每个学生选修了几门课程。如果等于C表课程的总数,就是我们要找的S# having count(*) = (select count(*) from C))--统计C表中共有几门课程
第二种:
问题:查询选修了全部课程的学生的学号和姓名。
可以转换为:查询没有一门课没有被该生选择的学生的学号和姓名。
相应的SQL语言如下:
select S#,SNAME -- 在 S 表里选 S#,SNAME from S where not exists -- 不存在 (select * -- 课程 from C where not exists -- 没有 (select * -- 被该生选择的课程 from SC where SC.S#=S.S# and SC.C#=C.C#)) -- 相关查询,三个表进行连接
这个查询语句可以这样理解:
查询没有一门课没有被该生选择的学生的学号和姓名。
第一个select 必定是在 S 表里选 S#,SNAME
select S#,SNAME
from S
where (不存在)
第二个select 是课程,来自C表)
select *
from C
where (没有)
第三个select是课程被该生选择,来自SC表)
select *
from SC
where (SC学号对应S表学号,SC表课程号对应C表课程号)
二、SQL语言查询选修了学号为“2001050105”的学生所选全部课程的学生姓名。
问题:查询选修了学号为“2001050105”的学生所选全部课程的学生姓名。
可以转换为:查询没有一门课(被学号“2001050105”的学生选择的课)没有被该生选择的学生的姓名。
相应的SQL语言如下:
select St_Name -- 从st_info表中选择姓名 from st_info where not exists -- 不存在 (select * --被学号为‘2001050105’的学生选择的课程 from s_c_info as sc_1 where st_id='2001050105' and not exists --没有 (select * --被该生选择 from s_c_info as sc_2 where sc_2.st_id=st_info.St_ID and sc_2.c_no=sc_1.c_no))
这个查询语句可以这样理解:
查询没有一门课(被学号“2001050105”的学生选择的课)没有被该生选择的学生的姓名。
第一个select从st_info 中选出St_name
select St_Name
from st_info
where (不存在)
第二个select 是从s_c_info表中选出学号为“2001050105”的学生选择的课程
select *
from s_c_info as sc_1
where st_id='2001050105' and (不存在)
第三个select是从s_c_info表中选出课程被该生选择的记录
select *
from s_c_info as sc_2
where(sc_2学号对应st_info学号,sc_2表课程号对应sc_1表的课程号)
之所以起别名sc_1和sc_2主要是他们来自同一个表,但是我们首先是从s_c_info表中选出了学号为“2001050105”的学生的选修记录并放到了sc_1中,这样在最后关联的时候就可以直接关联。
三、总结:
上述两个问题,其实解题思维是一样的,都是运用了两次 not exists 双重否定表示肯定,理解了这两个问题,在遇到相似的问题,可以进行相应的转化。那么该问题既然是双重否定,那么可不可以用两个 exists 呢?显然不可以。自己思考一下吧。如果理解了上述问题,很简单的就可以知道原因。