SELECT:【例3.49】~【例3.59】
REF:教材3.4“数据查询”的部分例题
1. 在SQLserver上运行,观察运行效果,并把代码写到作业中。
2. 写出自己的理解/收获/心得体会(部分比较复杂的例题,建议增加测试方法和测试数据,举一反三)。
REF:建表&插入数据
作业原地址:作业
目录
-
连接查询
若一个查询同时涉及两个以上的表,则称之为链接查询。
链接查询是关系数据库中最主要的查询,包括等值连接查询、自然连接查询、非等值连接查询、自身连接查询、外连接查询和复合连接查询等。
1.等值与非等值连接查询
连接查询的WHERE子句用来连接两个表的条件称为连接条件或连接谓词。
[<表名1>.]<列名1> <比较运算符> [<表名2>.]<列名2>
其中比较运算符主要有=、>、<、>=、<=、!=等。
连接谓词中的列名称为连接字段。各连接字段类型必须是可比的。
【例3.49】查询每个学生及其选修课程的情况。
SELECT Student.*, SC.*
FROM Student, SC
WHERE Student.Sno = SC.Sno; /*将Student与SC中同一学生的元组连接起来*/
【例3.50】对例3.49用自然连接完成。
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student,SC
WHERE Student.Sno = SC.Sno;
【例3.51】查询选修2号课程且成绩在90分以上的所有学生的学号和姓名。
SELECT Student.Sno,Sname
FROM Student,SC
WHERE Student.Sno=SC.Sno AND /*连接谓词*/
SC.Cno='2' AND SC.Grade>90; /*其他限定条件*/
注:查询顺序为先查询SC.Con='2',再查询SC.Grade>90。
2.自身链接
一个表与其自己进行连接,称为表的自身连接。
【例3.25】查询每一门课的间接先修课(即先修课的先修课)。
注:将Course表与其自身连接。要为Course表取两个别名,FIRST,SECOND。
SELECT FIRST.Cno,SECOND.Cpno
FROM Course FIRST,Course SECOND
WHERE FIRST.Cpno = SECOND.Cno;
3.外连接
于2.4.2节提到过外连接、左外连接、右外连接
外连接:把悬浮元组也保存在结果关系中,而在其他属性上填空值(NULL),那么这种连接就叫做外连接。
左外连接:如果只保留左边关系R中的悬浮元组,就叫做左外连接。
右外连接:如果值保留右边关系S中的悬浮元组,就叫做右外连接。
【例3.53】
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student LEFT OUTER JOIN SC ON(Student.Sno=SC.Sno);
/*也可以使用USING来去掉结果中的重复值:FROM Student LEFT OUTER JOIN SC USING (Sno);*/
4.多表连接
多表连接:两个以上的表进行连接。
【例3.54】查询每个学生的学号、姓名、选修的课程名及成绩
SELECT Student.Sno,Sname,Cname,Grade
FROM Student,SC,Course
WHERE Student.Sno=SC.Sno AND SC.Cno=Course.Cno;
-
嵌套查询
一个SELECT-FROME-WHERE语句称为一个查询块。
将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为:嵌套查询。
例如:
SELECT Sname /*外层查询或父查询*/
FROM Student
WHERE Sno IN
(SELECT Sno /*内层查询或子查询*/
FROME SC
WHERE Cno='2');
注:可以用多个简单查询构成复杂的查询。
1.带有IN谓语的子查询
【例3.55】查询与“刘晨”在同一个系学习的学生。
步骤:先分布来完成此查询,然后再构造嵌套查询。
/*确定“刘晨”所在系名*/
SELECT Sdept
FROM Student
WHERE Sname='刘晨'; /*结果为CS*/
/*查找所有在CS系学习的学生。*/
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept='CS';
不相关子查询:
子查询的查询条件不依赖于父查询。
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept IN
(SELECT Sdept
FROM Student
WHERE Sname='刘晨');
自身连接:
SELECT S1.Sno,S1.Sname,S1.Sdept
FROM Student S1,Student S2
WHERE S1.Sdept=S2.Sdept AND S2.Sname='刘晨';
【例3.56】查询选修了课程名为“信息系统”的学生学号和姓名。
SELECT Sno,Sname /*最后在Student关系中取出Sno和Sname*/
FROM Student
WHERE Sno IN
(SELECT Sno /*然后在SC关系中找出选修了3号课程的学生学号*/
FROM SC
WHERE Cno IN
(SELECT Cno /*首先在Course关系中找出“信息系统”的课程号,为3号*/
FROM Course
WHERE Cname='信息系统'
)
);
连接查询:
SELECT Student.Sno,Sname
FROM Student,SC,Course
WHERE Student.Sno=SC.Sno AND
SC.Cno=Course.Cno AND
Course.Cname='信息系统';
注:如果子查询的查询条件依赖于父查询,这类子查询称为相关子查询,整个查询语句称为相关嵌套查询语句。
3.带有比较运算符的子查询
指父查询与子查询之间用比较运算符进行连接。>、<、=、>=、<=、!=或<>等。
例如在【例3.55】中,由于一个学生只可能在一个系学习,也就是说内查询的结果收到一个值,因此可以用=代替IN:
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept=(SELECT Sdept
FROM Student
WHERE Sname='刘晨');
【例3.57】找出每个学生超过他选修课程平均成绩的课程号。
SELECT Sno,Cno
FROM SC x
WHERE Grade>=(SELECT AVG(Grade)
FROM SC y
WHERE y.Sno=x.Sno);
x:是表SC的别名,又称为元组变量,可以用来表示SC的一个元组。
步骤:
①从外层查询中取出SC的一个元组x,将元组x的Sno值(201215121)传送给内层查询;
②执行内层查询,得到值88(近似值),用该值代替内层查询,得到外层查询;
③执行这个查询。
然后外层查询取出下一个元组重复上述步骤,直到外层的SC元组全部处理完毕。
3.带有ANY(SOME)或ALL谓语的子查询
>ANY | 大于子查询结果中的某个值 |
>ALL | 大于子查询结果中的所有值 |
<ANY | 小于子查询结果中的某个值 |
<ALL | 小于子查询结果中的所有值 |
>=ANY | 大于等于子查询结果中的某个值 |
>=ALL | 大于等于子查询结果中的所有值 |
<=ANY | 小于等于子查询结果中的某个值 |
<=ALL | 小于等于子查询结果中的所有值 |
=ANY | 等于子查询结果中的某个值 |
=ALL | 等于子查询结果中的所有值 (通常没有实际意义) |
!=(或<>)ANY | 不等于子查询结果中的某个值 |
!=(或<>)ALL | 不等于子查询结果中的任何一个值 |
【例3.58】查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄。
SELECT Sname,Sage
FROM Student
WHERE Sage<ANY(SELECT Sage
FROM Student
WHERE Sdept='CS')
AND Sdept<>'CS'; /*注:这是父查询块中的条件*/
步骤:先处理子查询,找出CS系中所有学生的年龄,构成一个集合(20,19);然后处理父查询,找所有不是CS系且年龄小于20 或 19的学生。
聚集函数:
SELECT Sname,Sage
FROM Student
WHERE Sage <
(SELECT NAX(Sage)
FROM Student
WHERE Sdept='CS')
AND Sdept<>'CS';
步骤:首先用子查询找出SC系中最大年龄(20),然后在父查询中查所有非CS系且年龄小于20岁的学生。
【例3.59】查询非计算机科学系中比计算机科学系所有学生年龄都小的学生姓名及年龄。
SELECT Sname,Sage
FROM Student
WHERE Sage < ALL
(SELECT Sage
FROM Student
WHERE Sdept='CS')
AND Sdept<>'CS';
聚集函数:
SELECT Sname,Sage
FROM Student
WHERE Sage <
(SELECT MIN(Sage)
FROM Student
WHERE Sdept='CS')
AND Sdept<>'CS';
总结:
这次作业基本都是查询。照着例题做,目前没遇到什么错误或者问题。感觉这个好像和离散数学差不多,各种逻辑,比如查询的顺序步骤,代码不一样,查询的方式也不一样。
代码差不多能看的懂了,跟做数学题套公式似的,敲多了也熟练了。不过这次费时间的还是敲代码,一个一个敲还是累啊。
上期传送阵:【数据库】作业6——SQL练习3 - SELECT(单表查询)
下期传送阵:————
!!!备注!!!————忘记发截图了(之后补上)
完成时间:2h19min
以上
————(2020.3.22)