数据库系统概论——第三章 关系数据库标准语言SQL(三)
一、 链接查询
连接查询:同时涉及两个以上表的查询 连接条件
连接谓词:用于连接两个表的条件 连接字段:连接谓词中的列名称
连接条件中的各连接字段类型必须是可比的,但名字不必相同
1. 等值与非等值链接
等值链接:链接运算符为=
eg:查询每个学生及其选修课程的情况
(1)嵌套循环法(nested-loop)
首先在表1中找到第一个元组,然后从头开始扫描表2,逐一查找满足连接件的元组,找到后就将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组。
表2全部查找完后,再找表1中第二个元组,然后再从头开始扫描表2,逐一查找满足连接条件的元组,找到后就将表1中的第二个元组与该元组拼接起来,形成结果表中一个元组。
重复上述操作,直到表1中的全部元组都处理完毕
(2)排序合并法(sort-merge)
常用于=连接
首先按连接属性对表1和表2排序
对表1的第一个元组,从头开始扫描表2,顺序查找满足连接条件的元组,找到后就将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组。当遇到表2中第一条大于表1连接字段值的元组时,对表2的查询不再继续
找到表1的第二条元组,然后从刚才的中断点处继续顺序扫描表2,查找满足连接条件的元组,找到后就将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组。直接遇到表2中大于表1连接字段值的元组时,对表2的查询不再继续
重复上述操作,直到表1或表2中的全部元组都处理完毕为止
(3)索引链接(index-join)
对表2按连接字段建立索引
对表1中的每个元组,依次根据其连接字段值查询表2的索引,从中找到满足条件的元组,找到后就将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组
自然链接
一条SQL语句可以同时完成选择和连接查询,这时WHERE子句是由连接谓词和选择谓词组成的复合条件
eg:查询选修2号课程且成绩在90分以上的所有学生的学号和姓名。
执行过程:先从SC中挑选出Cno='2’并且Grade>90的元组形成一个中间关系;再和Student中满足连接条件的元组进行连接得到最终的结果关系。
2. 自身链接
自身链接:一个表与其自己进行链接
需要给表其别名以示区别
鱼油所有属性名都是同名属性,因此必须使用别名前缀
3. 外连接
外连接与普通连接的区别
(1)普通连接操作只输出满足连接调节的元组
(2)外连接操作以指定表为连接为主体,将主表中不满足连接条件的元组一并输出
(3)左外连接:列出左边关系中所有的元组
(4)右外连接:列出右边关系中所有的元组
是将两个表的满足连接条件的所有数据(即内连接数据),
再加上那些“左边”表中,不能满足连接条件的数据的总和。
对于左边表中不能满足条件的数据,则,在结果中的右边部分,都补上“null”(空值);
4. 多表链接
多表链接:两个以上的表进行链接
二、嵌套查询
一个select-from-where语句称为一个查询块
将一个查询块嵌套在另一个查询块的where子句或having短语的条件中的查询称为嵌套查询
上层的查询块称为外层查询或父查询
下层的查询称块为内层查询或子查询
sql语言允许多层嵌套查询:即一个子查询中还可以嵌套其他子查询
子查询的限制:不能使用order by子句
不相关子查询:子查询的查询条件不依赖与父查询,
由里向外 逐层处理。即每个子查询在上一级查询处理之前求解,子查询的结果用于建立其父查询的查找条件。
相关子查询:子查询的查询条件依赖于父查询。(1)首先取外层查询中表的第一个元组,根据它与内层查询相关的属性值处理内层查询,若WHERE子句返回值为真,则取此元组放入结果表(2)然后再取外层表的下一个元组(3)重复这一过程,直至外层表全部检查完为止
1. 带有in谓词的子查询
eg:查询与“刘晨”在同一个系学习的学生。
方法一:分步查询
(1)确定“刘晨”所在系名
(2)查找所有在CS系学习的学生
方法二:嵌套查询(不相关子查询)
方法三:用自身连接完成
2. 带有比较运算符的子查询
当确切指导内层查询返回单值时,可用比较运算符(>,<,=,>=,<=,!=或<>)
可能的执行过程
(1)从外层循环中取出sc的一个元组x,将元组x的sno值(201215121)传送给内层循环
SELECT AVG(Grade)
FROM SC y
WHERE y.Sno='201215121‘;
(2)执行内层循环,得到值88.3(近似值),用该值代替内层查询,得到外层查询:
select sno,cno
from sc x
where grade>=88.3;
(3)执行这个查询,得到
(201215121,1)
(4)然后外层取出下一个元组重复1-3步骤,直到外层的sc元组全部处理完毕。
3. 带有any(some)或all谓词的子查询
eg:查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄
存在量词 ∃
带有exists谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”
若内层查询结果非空,则外层的where子句返回真值
若内存查询结果为空,则外层的where子句返回假值
由exists引出的子查询,其目标列表达式通常都用*,因为带exists的子查询值返回真值或假值,给出列名无实际意义。
not exists谓词
若内层查询结果非空,则外层的where子句返回假值
若内层查询结果为空,则外层的where子句返回真值
eg:查询所有选修了1号课程的学生姓名。
(1)不同形式的查询间的替换
1) 一些带exists或not exists谓词的子查询不能被其他形式的子查询等价替换
2) 所有带IN谓词、比较运算符、ANY和ALL谓词的子查询都能用带EXISTS谓词的子查询等价替换
(2)用exists/not exists实现全称量词(难点)
1)sql语言中没有全称量词
2)可以把得有全称量词的谓词转换为等价的带有存在量词的谓词:
eg:
(3)用exists/not exists实现逻辑蕴含(难点)
1)sql语言中没有蕴含逻辑运算
2)可以利用谓词演算将逻辑蕴含谓词等价转换为:
p q 结果
0 1 1
0 0 1
1 0 0
1 1 1
例题:查询至少选修了学生201215122选修的全部课程的学生号码。
4. 集合查询
(1)集合操作的种类
1)并操作union
2)交操作intersect
3)差操作except
(2)参加集合操作的个查询结果的列数必须相同;对应项的数据类型也必须相同
(3)mysql中只有union没有intersect 与except
UNION:将多个查询结果合并起来时,系统自动去掉重复元组
UNION ALL:将多个查询结果合并起来时,保留重复元组
eg:查询计算机科学系的学生与年龄不大于19岁的学生 的交集。(下面的方法mysql不适用,可以用其他方法代替)
eg:查询既选修了课程1又选修了课程2的学生。
eg:查询计算机科学系的学生与年龄不大于19岁的学生的差集。下面的方法mysql不适用,可以用其他方法代替)
5. 基于派生表的查询
子查询不仅可以出现在where子句中,还可以出现在from子句中,这是子查询生成的临时派生表(derived table)成为主查询的查询对象
如果子查询中没有聚集函数,派生表可以不指定属性列,子查询SELECT子句后面的列名为其缺省属性。