(15)查询读者表中读者总人数
select count(*) as 读者总人数 from gzh_readers
(16)查询借书天数大于20天的借阅信息
select *,(gzh_htime-gzh_jtime) as 借阅天数 from gzh_borrow where (gzh_htime-gzh_jtime)>20 order by 借阅天数 desc;
(17)查询读者表中各个专业下的学生人数,字段名分别为专业名称、读者人数
select gzh_speciality as 专业名称, count(*) as 读者人数 from gzh_readers GROUP BY gzh_speciality
(18)查询累计借书最多的读者信息
select * from gzh_readers where gzh_rnum =(select max(gzh_rnum) from gzh_readers)
(19)查询借书日期最早的读者
select * from gzh_readers r ,gzh_borrow w where r.gzh_rno=w.gzh_rno and gzh_jtime =(select min(gzh_jtime) from gzh_borrow)
(20)查询借阅天数最长的借阅信息
select *,max(gzh_htime-gzh_jtime) as 借阅天数最长 from gzh_borrow
(21)学校图书馆出台了一项借阅评级政策,想通过借阅量评借阅之星,评级如下:
借阅3本以下,评为普通借阅者
借阅3-5本,评为优质借阅者
借阅5-9本,评为优秀借阅者
借阅9本以上,评为借阅之星
要求:输出读者的编号、姓名、专业、违规情况、借阅量和评级状况,并按评级高到低排列
select gzh_rno as 读者号, gzh_rname as 姓名,gzh_speciality as 专业,gzh_remarks as 违规情况,gzh_rnum as 借阅量, case when gzh_rnum>9 then '借阅之星' when gzh_rnum>5 and gzh_rnum<=9 then '优秀借阅者' when gzh_rnum>3 and gzh_rnum<=5 then '优质借阅者' else '普通借阅者' end as 评级状况 from gzh_readers order by gzh_rnum desc;
2、多表操作
(1)要求查询读者编号、读者姓名、性别、专业、借阅的书籍、管理员姓名、累积借书、违规情况、借书日期、还书日期并按读者编号升序排列
SELECT r.gzh_rno AS 读者编号, r.gzh_rname AS 读者姓名, r.gzh_rsex AS 性别, r.gzh_speciality AS 专业, b.gzh_bname AS 借阅的书籍, l.gzh_lname AS 管理员姓名, r.gzh_rnum AS 累积借书, r.gzh_remarks AS 违规情况, w.gzh_jtime AS 借书日期, w.gzh_htime AS 还书日期 FROM gzh_readers r, gzh_books b, gzh_librarian l, gzh_borrow w WHERE w.gzh_rno = r.gzh_rno AND w.gzh_bno = b.gzh_bno AND w.gzh_lno = l.gzh_lno ORDER BY r.gzh_rno ASC;
(2)查询借书总天数>200天读者的所有借阅情况(可能有多次借书的经历),包括读者号、姓名、借书、还书日期以及借书总天数,并按借书总天数降序排列。
select r.gzh_rno as 读者号,r.gzh_rname as 读者姓名,w.gzh_jtime as 借书日期,w.gzh_htime as 还书日期 ,(w.gzh_htime-w.gzh_jtime) as 借书总天数 from gzh_readers r inner join gzh_borrow w on r.gzh_rno=w.gzh_rno HAVING 借书总天数>200 ORDER BY 借书总天数 desc;
(3)查询借阅书籍时间>200天的读者名字、读者号,且读者号为5~10
SELECT gzh_rno as 读者号,gzh_rname as 读者名字 FROM gzh_readers WHERE gzh_rno IN ( SELECT gzh_rno FROM gzh_borrow WHERE ( gzh_htime - gzh_jtime )> 200 ) and gzh_rno BETWEEN 5 and 10;
(4)查询专业为“软件工程”且读者号大于等于10的读者借阅书籍的情况,包括读者的基本信息和借阅情况
select * from gzh_readers r left join gzh_borrow w on r.gzh_rno=w.gzh_rno where r.gzh_speciality='软件工程' and r.gzh_rno>=10;
(5) 查询姓周的书籍管理人员的姓名以及被该管理人员借记过书籍的读者姓名、专业、书籍名
select r.gzh_rname as 读者姓名,r.gzh_speciality as 专业, l.gzh_lname as 管理人员姓名,b.gzh_bname as 书籍名字 from gzh_readers r,gzh_librarian l,gzh_borrow w,gzh_books b where r.gzh_rno=w.gzh_rno and w.gzh_lno=l.gzh_lno and w.gzh_bno=b.gzh_bno and l.gzh_lname like '周%';
(6) 学校现想统计出版社借阅总量>=2的借阅信息,要求输出出版社的名称、借阅数量,并按借阅量降序排列
select b.gzh_press as 出版社,count(*) as 借阅量 from gzh_books b,gzh_borrow w where b.gzh_bno=w.gzh_bno GROUP BY gzh_press Having 借阅量>=2 ORDER BY 借阅量 desc;
(7) 查询被借阅最多的前三本书籍,要求输出书籍名称,出版社,借阅量并按借阅量降序排列
select b.gzh_bname as 书籍名称,b.gzh_press as 出版社,count(*) as 借阅量 from gzh_books b,gzh_borrow w where w.gzh_bno=b.gzh_bno group by b.gzh_bno order by 借阅量 desc limit 0,3;
八、求关系模式的候选码
给出一个关系模式R,其中U={A,B,C,D,E,F,G},F={ABC,CDE,EA,AG},求候选码
候选码选取规则:
1、只在右边出现的属性,不属于候选码;
2、只在左边出现的属性,一定存在于某候选码当中;
3、外部属性一定存在于任何候选码当中;
4、其他属性逐个与2,3的属性组合,求属性闭包,直至X的闭包等于U,若等于U,则X为候选码。
L:A,B,C,D,E
R:C,E,A,G
N: F
1、只在右边出现的一定不是候选码,所以候选码不包含G
2、在左边出现的B、D,属于主属性,一定存在于某候选码当中
3、既不出现在左边又不出现在右边的F,属于主属性,一定存在于某候选码当中
所以有可能是候选码的是BDF、BDCF、BDEF、BDAF
(BDF)+BDFU
(BDCF)+BDCFEAG=U
(BDEF)+BDEFAGC=U
(BDAF)+BDAFGCE=U
注:(X)+是表示属性闭包,用我的话来解释一下闭包,就是包括元素本身以及以它为基点,所能推导出的所有元素组成的一个集合。
所以由上可知候选码是BDCF、BDEF、BDAF这三个,最小函数依赖集为F={ABC,CDE,EA,AG}
再来一道题目练练手
设有关系模式R(A,B,C,D,E),其上的函数依赖集:U={A→BC,CD→E,B→D,E→A},求出R的所有候选关键字。
解:
L:A,B,C,D,E
R:A,B,C,D,E
N:无
乍一看,怎么和我们上述做的不一样呢?其实都是一样的。左右边都没有单独出现元素,所以无法判断候选码包含哪个元素。A,B,C,D,E和两两组合都有可能是候选码。
(A)+BCDEA=U,所以A是候选码,所以和A组合的诸如AB、AC等都可以排除。(E)+EABCD=U,所以E也是候选码,和E的组合可以排除。
(B)+BD U,B不是候选码,但BC、BD有可能是候选码
(BC)+BCDEA=U,BC是候选码
(BD)+BDU,BD不是候选码
以此类推,可以得到候选码为A,BC,CD,E。
九、最小函数依赖集
求解最小函数依赖集分三步:
1、将F中的所有依赖右边化为单一元素
2、去掉F中所有冗余依赖关系
3、去掉F中的所有依赖左边的冗余属性
给出一个关系模式R,其中U={A,B,C,D,E,F,G,H,I,J},F={ABDE,ABG,BF,CJ,CJI,GH},求最小函数依赖集
1、将F中的所有依赖右边化为单一元素
F={ABDE,ABG,BF,CJ,CJI,GH}
2、去掉F中所有冗余依赖关系
简单来说,从第一个函数依赖XY开始将其从F中去掉,然后在剩下的函数依赖中求X的闭包X+,看X+是否包含Y,若是,则去掉XY;否则不能去掉,依次下去直到找不到冗余的函数依赖。
(1)去掉ABDE,(ABD)+ABDGFH,不包含E,所以不冗余,不能去掉。
(2)去掉 ABG,(AB)+ABF,不包含G,所以不冗余,不能去掉。
(3)去掉 BF,(B)+B,不包含F,所以不冗余,不能去掉。
(4)去掉CJ,(C)+C,不包含J,所以不冗余,不能去掉。
(5)去掉CJI,(CJ)+CJ,不包含I,所以不冗余,不能去掉。
(6)去掉GH,(G)+G,不包含H,所以不冗余,不能去掉。
所以,F= {ABDE,ABG,BF,CJ,CJI,GH}
3、去掉F中的所有依赖左边的冗余属性
简单来说,一个一个地检查函数依赖左部非单个属性的依赖。例如XYA,若要判断Y为多余元素,则以XA代替XYA是否等价?若A属于(X)+,则Y是多余属性,可以去掉。同理,若要判断X多余元素, 则以YA代替XYA看是否等价。
(1)ABDE去掉A,(BD)+BDF不包含E,同理可得BD都不是冗余元素。
(2)ABG,因为G只能由AB推出,所以AB都不是冗余元素。
(3)CJI,去掉C,(J)+J,不包含I,所以C不能去掉;去掉J,(C)+CJI,包含I,所以J是冗余元素。CJI变为CI。
综上所诉,所求的最小函数依赖集为F={ABDE,ABG,BF,CJ,CI,GH} ,只有一个候选码,且为ABDC
十、模式分解
例题:U=(A,B,C,D,E) ,F={ABC,CB,DE,DC} 若R不是3NF,将R分解为无损且保持函数依赖的3NF。
我们先把前面的知识串起来,先求候选码,再求函数依赖,再进行模式分解
L:A,B,C,D
R:B,C,E
N:无
可能候选码:AD、ADB、ADC
(AD)+ADECB=U,所以候选码是AD,且为唯一候选码
最小函数依赖:
1、所有右边已经是单一元素了,不用拆分
2、去掉F中所有冗余依赖关系
去掉ABC,(AB)+AB,不包含C,所以不冗余,不能去掉
去掉CB,(C)+C,不包含B,所以不冗余,不能去掉
去掉DE,(D)+DCB,不包含E,所以不冗余,不能去掉
去掉DC,(D)+DE,不包含C,所以不冗余,不能去掉
所以, F={ABC,CB,DE,DC}
3、去掉F中的所有依赖左边的冗余属性
ABC,去掉B,(A)+A,不包含C,B不是冗余元素,不能去掉,同理A也不是冗余元素。
故最小函数依赖集为Fm= {ABC,CB,DE,DC}
模式分解:
已知候选码为AD,为第一范式,原因如下:
在关系模式中若没有非主属性对码的部分函数依赖即可称为2NF。何为主属性?候选码里的每个元素都属于主属性,比如:A,D。何为非主属性?剩下的即是,B,C,E。如何解读范式那句话?因为DC,C依赖于D,D又是候选码的主属性,所以说存在C部分函数依赖于AD,所以不是第二范式。在关系型数据库中一定存在一个范式,所以它必为第一范式。
第一步:左部相同原则分组:对Fm按具有相同左部的原则分组,然后左部∪右部。
U1=ABC U2=BC U3=DCE( DE,DC由于具有相同的左部,故进行合并)
第二步:看有没有包含关系,有的话,合并吸收。
将R分解为
ρ={ R1({A,B,C},{ABC}),
R2({B,C},{CB}),
R3({D,C,E},{DE,DC}) }
我们可以看见R1,R2存在包含关系,
故进行合并吸收
ρ={ R1({A,B,C},{ABC,CB}),
R2({D,C,E},{DE,DC}) }
第三步:判断是不是无损连接
若关系模式R(U,F)中,被分解为p={R1, R2}是R的⼀个分解,若R1∩R2 R1 - R2或者R1∩R2 R2 - R1,则为无损连接。
R1∩R2为C,R1-R2=AB,C不能推出AB,即 R1∩R2 不能推出R2 - R1,故不是无损连接,需添加候选码R3({A,D},{∅})。
所以模式分解的结果为:
ρ={ R1({A,B,C},{ABC,CB}),
R2({D,C,E},{DE,DC}) ,
R3({A,D},{∅}) }