本节课主要学习了数据查询中的连接查询。
例3.48查询平均成绩大于等于90分的学生学号和平均成绩。
select Sno,avg(Grade)
from SC
group by Sno
having avg(Grade)>80;
这里使用了having短语,主要原因是where子句不支持使用聚合函数作为条件表达式。
(平均值我使用的是80)
连接查询
1.等值于非等值连接查询
例3.49查询每个学生及其选修课程的情况。
没有等值连接的情况下:
select Student.*,SC.Cno
from Student,SC;
显然这不是正确结果,而是这两个表的笛卡尔积。如果规定了他们的公共属性Sno,结果就是正确的了。
select Student.*,SC.Cno
from Student,SC
where Student.Sno=SC.Sno;
select Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
from Student,SC
where Student.Sno=SC.Sno;
如果属性名在参加连接的个表中是唯一的,则可以省略表名前缀,结果是一样的。(例3.49中的SC.Cno改为SC.*后结果一致)
例3.51查询选修2号课程且成绩在80分以上的所有学生的学号和姓名。
select SC.Sno,Sname
from SC,Student
where Grade>80 and SC.Cno='2' and SC.Sno=Student.Sno;
例3.52 查询每一门课程的间接先修课(即先修课的先修课)。
课程都在Course表中,但是表中没有直接提到间接先修课,不过如果将表自身和自身连接,就可以找出间接先修课。
我们可以将Course取两个别名,一个first,一个second。
select first.Cno,second.Cpno
from Course first,Course second
where first.Cpno=second.Cno;
外连接
有时想以Student表为主体列出每个学生的基本情况及其选课结果。若每个学生没有选课,仍把Student的悬浮元组保存在结果关系中,就需要用到外连接了。
例3.53改写例3.49
如果:
select Student.*,Cno,Grade
from Student,SC
where Student.Sno=SC.Sno
--左外连接
select Sname,Student.Sno,Ssex,Sage,Sdept,Cno,Grade
from Student left outer join SC on(Student.Sno=SC.Sno);
--右外连接
select Sname,Student.Sno,Ssex,Sage,Sdept,Cno,Grade
from Student right outer join SC on(Student.Sno=SC.Sno);
结果为:
不同点:左外连接列出左边关系(Student)中的所有元组,右外连接列出右边关系(SC)中的所有元组。
多表连接
连接操作还可以进行两个以上的表进行连接。
例3.54 查询每个学生的学号、姓名、选修的课程名以及成绩。
select Sname,Grade,Cname,Student.Sno
from Student,SC,Course
where Student.Sno=SC.Sno and SC.Cno=Course.Cno;