1、【数据库原理】关系代数篇除法讲解陈宇超编辑总结:除法运算的一般形式示意图如何计算 RS 呢,首先我们引进”象集” 的概念,具体意义看下面的陈述即可理解关系 R 和关系 S 拥有共同的属性 B、C , RS 得到的属性值就是关系 R 包含而关系 S 不包含的属性,即 A 属性在 R 关系中 A 属性的值可以取 a1,a2,a3,a4 a1 值对应的象集为 (b1,c2) , (b2,c1) , (b2,c3) a2 值对应的象集为 (b3,c7) , (b2,c3) a3 值对应的象集为 (b4,c6) a4 值对应的象集为 (b6,c6) 关系 S 在 B、C 上的投影为 (b1,c2) ,
2、(b2,c1) , (b2,c3) 只有 a1 值对应的象集包含关系 S 的投影集,所以只有 a1 应该包含在 A 属性中所以 RS 为Aa1【例题一】为了更好的理解除法的实际作用,请看下面的例题设有教学数据库有 3 个关系( 以下四小问均用除法的思想解决)学生信息关系 student(sno,sname,age,sex)学生选课关系 sc(sno ,cno,score)学校课程关系 course(cno,cname )Student 表sno sname age sexS001 陈晓 16 男S002 周倩 21 女S003 华南 19 男S004 曹匀 21 女S005 郑威 20 男Co
3、urse 表cno cnameC001 计算机科学C002 诗歌鉴赏C003 资本论SC 表sno cno scoreS001 C001 88S001 C002 95S001 C003 99S002 C001 97S002 C003 84S003 C002 69S005 C002 77S005 C003 98SQL 语言中没有全称量词,具体实现时可以把带有全称量词的谓词转换为等价的带有存在量词的谓词。解决这类的除法问题一般采用双嵌套 not exists 来实现带全称量词的查询解决所谓 forall 的问题。(1) 检索所学课程包含了 C002 课程的学生学号解 关系代数表达式:sno ( s
4、ccno( cno=C002 (course) )Sql 语句从略(2) 求至少选择了 C001 和 C003 两门课程的学生学号解 关系代数表达式:sno ( sccno( cno=C001 or cno=C003(course) )Sql 语句select distinct sno from sc A where not exists(select * from course B where cno in (C002,C003) and not exists(select * from sc C where A.sno=C.sno and B.cno=C.cno)也可以采用自连接selec
5、t s1.sno from (select * from sc where cno=C001) as s1,(select * from sc where cno=C003) as s2 where s1.sno=s2.sno(3) 求至少学习了学生 S003 所学 课程的学生学号解 关系代数表达式:sno ( sccno( sno=S003 (sc) )select distinct sno from sc A where not exists(select * from sc B where sno=S003 and not exists(select * from sc C where
6、A.sno=C.sno and B.cno=C.cno)(4) 求选择了全部课程的学生的学号解 此例的等价自然语义是,输出这样的学号,不存在某门课程在他的选课记录里没有选这门课关系代数表达式:sno (sccno(course) )Sql 语句select distinct sno from sc A where not exists(select cno from course B where not exists (select * from sc C where C.sno=A.sno and C.cno=B.cno)(5) 求选择了全部课程的学生的学号和姓名解 关系代数表达式:sno,
7、sname(studentsc) cno(course) )Sql 语句select sno,sname from student A where not exists(select cno from course B where not exists (select * from sc C where C.sno=A.sno and C.cno=B.cno)以上小问用 group by 结合 count 语句也是可以实现的,也更好理解一些。例如求选择了全部课程的学生学号SELECT sno FROM (SELECT COUNT (*) cnt, SnoFROM SCGROUP BY sno ) TWHERE cnt = ( SELECT COUNT (Cno )FROM COURSE )求至少选择了 C002 和 C003 两门课程的学生学号select sno from sc where cno in(C002,C003) group by sno having COUNT(cno)=2但该方法对于一个学生多次选修一门课程的情况无法处理,需要对其中的 SC 关系用distinct进行一定预处理,所以group by +count有一定的局限性