《理学数据库第五章续嵌套查询与联合查询12学时习题讲解10》由会员分享,可在线阅读,更多相关《理学数据库第五章续嵌套查询与联合查询12学时习题讲解10(31页珍藏版)》请在金锄头文库上搜索。
1、理学理学数据库数据库 第五章第五章续续 嵌套查询与联合查嵌套查询与联合查询询1-2学时学时+习题讲解习题讲解_201210嵌套查询允许多层嵌套,体现了SQL的结构化特色术语父查询 & 子查询不相关子查询:子查询的查询条件不依赖于父查询相关子查询:子查询的查询条件依赖于父查询的某个属性值SELECT 姓名 FROM student_infoWHERE EXISTS(SELECT * FROM grade WHERE 学号=student_info.学号 AND 课程号 = 002);(不相关子查询)(相关子查询)SELECT 姓名 FROM student_infoWHERE 学号 IN(SEL
2、ECT 学号 FROM grade WHERE 课程号 = 002);2024/8/122嵌套查询不相关子查询的求解方法由里向外。子查询只执行一次,其结果用于父查询。相关子查询的求解方法内层查询与外层查询反复求值。首先取外层查询中表的第一条元组,根据它与内层查询相关的属性值处理内层查询,如果where子句返回值为真,则取此元组放入结果表中;然后再取外层查询中表的第二条元组;重复这一过程,直至外层查询中表的全部元组都被检查完为止。子查询中通常不含ORDER BY子句和DISTINCT短语,因为它们只对最终结果有意义。2024/8/1232024/8/1242024/8/125一、带有IN谓词的子
3、查询嵌套查询中,子查询的结果往往是一个集合,所以经常使用谓词IN使用嵌套实现此查询使用嵌套实现此查询SELECT 学号,姓名,院系FROM student_infoWHERE Sdept IN(SELECT 院系 FROM student_info WHERE 姓名= 刘晨)例例 查询与查询与“刘晨刘晨”在同一个系学习的学生在同一个系学习的学生先分步实现此查询先分步实现此查询(1) SELECT 院系 FROM student_info WHERE 姓名= 刘晨 结果为 IS(2) SELECT 学号,姓名,院系 FROM student_info WHERE 院系=IS(不相关子查询)202
4、4/8/126SELECT 学号,姓名(3)FROM Student_infoWHERE 学号 IN(SELECT 学号(2) FROM grade WHERE 课程号 IN (SELECT 课程号(1) FROM curriculum WHERE 课程名=信息系统)例例 查询选修了课程名为查询选修了课程名为“信息系统信息系统”的学生学号和姓名的学生学号和姓名n使用连接查询实现n使用嵌套查询实现 多种实现方式,嵌套查询具有结构化程序设计特点SELECT学号,姓名FROM Student_info s, grade g, curriculum cWHERE s.学号 = g.学号 AND g.课
5、程号 = c.课程号 AND c.课程名= 信息系统(不相关子查询)2024/8/127NOTINNOTIN子查询子查询操作符IN用于子查询,用来确定某个列值是否在内部查询的结果集中。 【例】查询借阅了青山出版社的图书的读者编号。 这个查询操作用子查询的方式来实现,可以分两步来构造子查询。 第第1 1步:步:找出青山出版社出版的所有图书的编号。 第第2 2步:步:查找借阅了青山出版社的图书的读者编号。 SELECT DISTINCT SELECT DISTINCT 读者编号读者编号 FROM borrowinfFROM borrowinf WHERE WHERE 图书编号图书编号 ININ (
6、 SELECT SELECT 编号编号 FROM booksFROM books WHERE WHERE 出版社出版社= =青山青山 )2024/8/12 【例】查询没有借阅图书的读者的详细情况。 SELECT * FROM readersSELECT * FROM readers WHERE WHERE 编号编号 NOT INNOT IN ( SELECT DISTINCT SELECT DISTINCT 读者编号读者编号 FROM borrowinfFROM borrowinf) 如果使用多表连接查询如果使用多表连接查询, ,如何实现如何实现? ? 2024/8/12二、带有比较运算符的子
7、查询当用户能确切知道内层查询返回的是单值时,可以使用比较运算符(,=,=,ANY(ALL) 大于子查询结果中的某个(所有)值=ANY(ALL) 大于等于子查询结果中的某个(所有)值=ANY(ALL) 小于等于子查询结果中的某个(所有)值=ANY(ALL) 等于子查询结果中的某个(所有)值!=ANY(ALL) 不等于子查询结果中的某个(任何)值2024/8/1211ALL :列值必须和内部查询结果集的每一个值进行比较,只有每一次的比较结果都为真时,比较结果才为真。ANY、SOME :列值和内部查询结果集的值进行比较,只要有一次为真,比较结果就为真。2024/8/1212例1SELECT 姓名,年
8、龄FROM student_infoWHERE 年龄 ANY(SELECT 年龄 FROM student_info WHERE 院系 = IS)AND 院系ISSELECT 姓名,年龄FROM student_infoWHERE 年龄 (SELECT MAX(年龄) FROM student_info WHERE 院系=IS)AND 院系IS例例 查询其他系中比信息系某一学生年龄小的查询其他系中比信息系某一学生年龄小的学生姓名和年龄学生姓名和年龄也可以用集函数来实现2024/8/1213例2SELECT Sname, SageFROM StudentWHERE Sage ALL(SELECT
9、 Sage FROM Student WHERE Sdept = IS)AND Sdept IS例例 查询其他系中比信息系所有学生年龄都小的查询其他系中比信息系所有学生年龄都小的学生姓名和年龄学生姓名和年龄SELECT Sname, SageFROM StudentWHERE Sage (SELECT MIN(Sage) FROM Student WHERE Sdept = IS)AND Sdept IS也可以用集函数来实现2024/8/1214转换关系事实上,用集函数实现子查询通常比直接用ANY或ALL查询效率要高ANY、ALL与集函数及IN的等价转换关系=!=ANYINMAXMIN=MIN
10、ALLNOT INMINMAX=MAX2024/8/1215四、NOTEXISTS 子查询 EXISTS是测试子查询是否有数据行返回,如果有则返回TRUE,否则返回FALSE。 NOT EXISTS 则相反,当结果表为空时,才返回TRUE。 【例】 对查询借阅了青山出版社的图书的读者编号,也可以用EXISTS子查询来实现: SELECT DISTINCT SELECT DISTINCT 读者编号读者编号 FROM borrowinfFROM borrowinf WHERE EXISTS WHERE EXISTS ( SELECT *SELECT * FROM books FROM books
11、WHERE books. WHERE books.编号编号=borrowinf.=borrowinf.图书编号图书编号 AND AND 出版社出版社= =青山青山) 2024/8/12 【例】 对查询没有借阅图书的读者的详细情况,同样也可以用NOT EXISTS子查询来实现: SELECT * SELECT * FROM readers FROM readers WHERE NOT EXISTS WHERE NOT EXISTS (SELECT * FROM borrowinf SELECT * FROM borrowinf WHERE borrowinf. WHERE borrowinf.读
12、者编号读者编号=readers.=readers.编号)编号) 2024/8/12u EXISTS代表“存在”,子查询只查找满足条件的那些记录,一旦找到第一个匹配的记录就马上停止查找。子查询不返回任何记录,只产生逻辑值“真”或“假”。u EXISTS采用的既不是等号,也不是IN,它作用的不是列之间的关系,而是表之间的关系。因此,在子查询的SELECT列表中不需要指定字段名,通常用SELECT *来代替。2024/8/12联合查询1 1、 UNION UNION操作符操作符 用于连接多个SELECT查询结果的集合操作有3种:并操作(UNION)、交操作(INTERSECTION)和差操作(MIN
13、US)。 UNION操作符的语法格式如下: SELECT_1 UNION ALL SELECT_1 UNION ALL SELECT_2 UNION ALL SELECT_3 SELECT_2 UNION ALL SELECT_3 2024/8/122024/8/1220联合查询1 1、 UNION UNION操作符操作符【例】查询青山出版社的图书编号和曾经被借阅的图书编号。 SELECT SELECT 编号编号 FROM books FROM books WHERE WHERE 出版社出版社= =青山青山 UNION UNION SELECT SELECT 图书编号图书编号 FROM bor
14、rowinfFROM borrowinf 如果使用了ALL选项,则所有结果行包括重复行都将被显示。在SELECT语句中,ALL选项是默认值,而在UNION运算符中,ALL选项不是默认值,必须要明确指定。2024/8/12【例】将titles表和discounts表的两个查询结果合并到一起。SELECT name=discounttype,value=discountFROM discountsUNIONSELECT title,ytd_salesFROM titlesWHERE title LIKE T%2024/8/1222 联合查询时,查询结果的列标题为第一个查询语句中的列标题,因此要定义
15、列标题时必须在第一个查询语句中定义。要对联合查询结果排序时,也必须使用第一查询语句中的列名。 SELECT name=discounttype,value=discountFROM discountsUNIONSELECT title,ytd_salesFROM titlesWHERE title LIKE T%ORDER BY value2024/8/12232 2、联合查询结果排序联合查询结果排序 联合查询也可以对结果进行排序,这时必须把ORDER BY子句与最后一个SELECT语句放在一起使用,而且要对第一个SELECT语句的列名进行排序。 【例】对上例的结果集按照编号的降序排序。 SE
16、LECT SELECT 编号编号 FROM booksFROM books WHERE WHERE 出版社出版社= =青山青山 UNION UNION SELECT SELECT 图书编号图书编号 FROM borrowinFROM borrowin ORDER BY 1 DESC ORDER BY 1 DESC2024/8/123 3、 对单张表使用对单张表使用UNIONUNION操作符操作符 使用UNION连接的所有SELECT语句也可以使用同一张表,此时UNION运算符可以用OR运算符来代替。 【例】查询蓝天出版社和碧水出版社的图书书名及作者姓名。 SELECT SELECT 书名书名,
17、 , 作者作者 FROM books FROM books WHERE WHERE 出版社出版社= =蓝天蓝天 UNIONUNION SELECT SELECT 书名书名, , 作者作者 FROM books FROM books WHERE WHERE 出版社出版社= =碧水碧水 2024/8/123 3、 对单张表使用对单张表使用UNIONUNION操作符操作符用OR运算符来代替UNION,查询语句可以改写为: SELECT SELECT 书名书名, , 作者作者 FROM booksFROM books WHERE WHERE 出版社出版社= =蓝天蓝天 OROR出版社出版社= =碧水碧
18、水2024/8/124 4、 交操作和差操作交操作和差操作 Transact-SQL不直接支持交操作和差操作,但可以使用EXISTS运算符来实现交操作,使用NOT EXISTS来实现差操作。 【例】查询曾经被借阅的青山出版社的所有图书编号。 SELECT SELECT 编号编号 FROM booksFROM books WHERE WHERE 出版社出版社= =青山青山 AND EXISTS AND EXISTS ( SELECT * ( SELECT * FROM borrowinf FROM borrowinf WHERE WHERE 编号编号= =图书编号图书编号) )2024/8/12
19、【例】查询没有被借阅过的青山出版社的所有图书编号。 SELECT SELECT 编号编号 FROM booksFROM books WHERE WHERE 出版社出版社= =青山青山 AND NOT EXISTS AND NOT EXISTS ( SELECT * ( SELECT * FROM borrowinf FROM borrowinf WHERE WHERE 编号编号= =图书编号图书编号) )2024/8/125 5、UNIONUNION操作符和操作符和JOINJOIN操作符区别与联系操作符区别与联系 UNION操作符和JOIN操作符都可以将两个或多个数据表连接在一起。但是,UNI
20、ON操作符通常是连接两个或者多个SELECT查询语句,而JOIN操作符则是在一个SELECT查询语句中将两个或者多个表连接在一起。 在有些情况下,同一个操作任务,可以使用UNION或者JOIN两种不同的查询策略。2024/8/126 6、 连接查询和子查询的比较连接查询和子查询的比较 有些问题使用子查询解决会更简单,有些问题使用连接查询可以变得简单,因此要根据实际情况进行选择。 当需要频繁地计算统计函数的值并将其用在外查询中作比较时,应该使用子查询。随着嵌套层数的增加,查询语句的性能会不断下降。 【例】查询books中价格最低的图书编号和书名。 SELECT SELECT 编号,书名编号,书名
21、 FROM booksFROM books WHERE WHERE 定价定价= =(SELECT min(SELECT min(定价定价) ) FROM books FROM books) 2024/8/12 当SELECT中的列来自于多于一个表时,则应该使用连接查询。但一般在INSERT,UPDATE和DELETE语句中不支持多表连接,要用子查询代替。 【例】查询读者编号、读者姓名、所借图书书名和借期。 SELECT readers.SELECT readers.编号,编号,readers.readers.姓名,姓名, books.books.书名,书名, borrowinf.borrowinf.借期借期 FROM readersFROM readers,booksbooks,borrowinfborrowinf WHERE readers. WHERE readers.编号编号=borrowinf.=borrowinf.读者编号读者编号 AND books.AND books.编号编号=borrowinf.=borrowinf.图书编号图书编号2024/8/12