西华师范大学计算机学院
第三章 关系数据库标准语言 SQL
(续 1)
3.3 查 询
? 3.3.1 概述
? 3.3.2 单表查询
? 3.3.3 连接查询
? 3.3.4 嵌套查询
? 3.3.5 集合查询
? 3.3.6 小结
3.3.3 连接查询
同时涉及多个表的查询称为连接查询 。 和单表查询的区
别是,连接查询中的 FROM子句后要指定查询涉及的多个表
名; WHERE子句中必须指定多表两两相连的连接条件 ; 在引
用表中同列名时, 要在列名前加表名, 形如, 表名,列
名,, 以示区别 。
? 用来连接两个表的条件称为连接条件或连接谓词
一般格式:
? [<表名 1>.]<列名 1> <比较运算符 > [<表名 2>.]<列名 2>
比较运算符,=,>,<,>=,<=,!=
? [<表名 1>.]<列名 1> BETWEEN [<表名 2>.]<列名 2> AND [<表
名 2>.]<列名 3>
连接查询 (续)
? 连接字段
– 连接谓词中的列名称为连接字段
– 连接条件中的各连接字段类型必须是可比的,
但不必是相同的
连接操作的执行过程
? 嵌套循环法 (NESTED-LOOP)
– 首先在表 1中找到第一个元组, 然后从头开始扫描表 2,
逐一查找满足连接件的元组, 找到后就将表 1中的第一
个元组与该元组拼接起来, 形成结果表中一个元组 。
– 表 2全部查找完后, 再找表 1中第二个元组, 然后再从
头开始扫描表 2,逐一查找满足连接条件的元组, 找到
后就将表 1中的第二个元组与该元组拼接起来, 形成结
果表中一个元组 。
– 重复上述操作, 直到表 1中的全部元组都处理完毕
排序合并法 (SORT-MERGE)
常用于等值 ( =) 连接
– 首先按连接属性对表 1和表 2排序
– 对表 1的第一个元组, 从头开始扫描表 2,顺序查找
满足连接条件的元组, 找到后就将表 1中的第一个
元组与该元组拼接起来, 形成结果表中一个元组 。
当遇到表 2中第一条大于表 1连接字段值的元组时,
对表 2的查询不再继续
排序合并法
– 找到表 1的第二条元组, 然后从刚才的中断点处继
续顺序扫描表 2,查找满足连接条件的元组, 找到
后就将表 1中的第一个元组与该元组拼接起来, 形
成结果表中一个元组 。 直接遇到表 2中大于表 1连接
字段值的元组时, 对表 2的查询不再继续
– 重复上述操作, 直到表 1或表 2中的全部元组都处理
完毕为止
索引连接 (INDEX-JOIN)
– 对表 2按连接字段建立索引
– 对表 1中的每个元组, 依次根据其连接字段
值查询表 2的索引, 从中找到满足条件的元
组, 找到后就将表 1中的第一个元组与该元
组拼接起来, 形成结果表中一个元组
连接查询 (续)
SQL中连接查询的主要类型
– 广义笛卡尔积
– 等值连接 (含自然连接 )
– 非等值连接查询
– 自身连接查询
– 外连接查询
– 复合条件连接查询
一、广义笛卡尔积
? 不带连接谓词的连接
? 很少使用
例:
SELECT Student.*,SC.*
FROM Student,SC
二、等值与非等值连接查询
等值连接, 自然连接, 非等值连接
[例 32] 查询每个学生及其选修课程的情况。
SELECT Student.*,SC.*
FROM Student,SC
WHERE Student.Sno = SC.Sno;
等值连接
? 连接运算符为 = 的连接操作
– [<表名 1>.]<列名 1> = [<表名 2>.]<列名 2>
– 任何子句中引用表 1和表 2中同名属性时, 都
必须加表名前缀 。 引用唯一属性名时可以加
也可以省略表名前缀 。
等值连接
假设 Student表,SC表分别有下列数据:
Student表
Sno Sname Ssex Sage Sdept
95001 李勇 男 20 CS
95002 刘晨 女 19 IS
95003 王敏 女 18 MA
95004 张立 男 19 IS
等值连接
SC表
Sno Cno Grade
95001 1 92
95001 2 85
95001
95002
95002
3
2
3
88
90
80
等值连接
结果表
Student.Sno Sname Ssex Sage Sdept SC.Sno Cno Grade
95001 李勇 男 20 CS 95001 1 92
95001 李勇 男 20 CS 95001 2 85
95001 李勇 男 20 CS 95001 3 88
95002 刘晨 女 19 IS 95002 2 90
95002 刘晨 女 19 IS 95002 3 80
自然连接
? 等值连接的一种特殊情况, 把目标列中
重复的属性列去掉 。
[例 33] 对 [例 32]用自然连接完成。
SELECT Student.Sno,Sname,Ssex,Sage,
Sdept,Cno,Grade
FROM Student,SC
WHERE Student.Sno = SC.Sno;
非等值连接查询
连接运算符 不是 = 的连接操作
[<表名 1>.]<列名 1><比较运算符 >[<表名 2>.]<列名 2>
比较运算符,>,<,>=,<=,!=
[<表名 1>.]<列名 1> BETWEEN [<表名 2>.]<列名 2> AND
[<表名 2>.]<列名 3>
三、自身连接
? 一个表与其自己进行连接,称为表的 自身连接
? 需要给表起别名以示区别
? 由于所有属性名都是同名属性,因此必须使用
别名前缀
自身连接(续)
[例 34] 查询每一门课的间接先修课 ( 即先
修课的先修课 )
SELECT FIRST.Cno,SECOND.Cpno
FROM Course FIRST,Course SECOND
WHERE FIRST.Cpno = SECOND.Cno;
自身连接(续)
FIRST表 ( Course表 )
Cno Cname Cpno Ccredit
1 数据库 5 4
2 数学 2
3 信息系统 1 4
4 操作系统 6 3
5 数据结构 7 4
6 数据处理 2
7 PASCAL语言 6 4
自身连接(续)
SECOND表 ( Course表 )
Cno Cname Cpno Ccredit
1 数据库 5 4
2 数学 2
3 信息系统 1 4
4 操作系统 6 3
5 数据结构 7 4
6 数据处理 2
7 PASCAL语言 6 4
自身连接(续)
查询结果
1 7
3 5
5 6
cno cpno
【 例 】 查询每个人的祖父姓名 。
假定个人情况表如表所示。
表 Person
显然, 要查出个人的祖父姓名, 必须将这个表
做自身连接 。 查询语句为:
SELECT First,Name,Second,F_name
FROM Person First,Person Second
WHERE First.F_name=Second.Name
这里 First和 Second分别是第一个 Person表
和第二个 Person表的别名 。
查询结果:
张成全 张福全
李向军 李福来
四、外连接( Outer Join)
? 外连接与普通连接的区别
– 普通连接操作只输出满足连接条件的元组
– 外连接操作以指定表为连接主体,将主体表
中不满足连接条件的元组一并输出
外连接(续)
[例 33] 查询每个学生及其选修课程的情况包括
没有选修课程的学生 ----用外连接操作
SELECT Student.Sno,Sname,Ssex,
Sage,Sdept,Cno,Grade
FROM Student,SC
WHERE Student.Sno = SC.Sno(*);
外连接(续)
结果:
Student.Sno Sname Ssex Sage Sdept Cno Grade
95001 李勇 男 20 CS 1 92
95001 李勇 男 20 CS 2 85
95001 李勇 男 20 CS 3 88
95002 刘晨 女 19 IS 2 90
95002 刘晨 女 19 IS 3 80
95003 王敏 女 18 MA
95004 张立 男 19 IS
外连接(续)
– 在表名后面加外连接操作符 (*)或 (+)指定非主
体表
– 非主体表有一, 万能, 的虚行, 该行全部由
空值组成
– 虚行可以和主体表中所有不满足连接条件的
元组进行连接
– 由于虚行各列全部是空值, 因此与虚行连接
的结果中, 来自非主体表的属性值全部是空

外连接(续)
? 左外连接
– 外连接符出现在连接条件的左边
? 右外连接
– 外连接符出现在连接条件的右边
五、复合条件连接
WHERE子句中含多个连接条件时, 称为复合条件连接
[例 35]查询选修 2号课程且成绩在 90分以上的所有学生的
学号、姓名
SELECT Student.Sno,student.Sname
FROM Student,SC
WHERE Student.Sno = SC.Sno AND
/* 连接谓词 */
SC.Cno= ' 2 ' AND /* 其他限定条件 */
SC.Grade > 90; /* 其他限定条件 */
多表连接
[例 36] 查询每个学生的学号, 姓名, 选修的课程名及成
绩 。
SELECT Student.Sno,Sname,Cname,Grade
FROM Student,SC,Course
WHERE Student.Sno = SC.Sno
and SC.Cno = Course.Cno;
结果:
Student.Sno Sname Cname Grade
95001 李勇 数据库 92
95001 李勇 数学 85
95001 李勇 信息系统 88
95002 刘晨 数学 90
95002 刘晨 信息系统 80
3.3 查 询
? 3.3.1 概述
? 3.3.2 单表查询
? 3.3.3 连接查询
? 3.3.4 嵌套查询
? 3.3.5 集合查询
? 3.3.6 小结
3.3.4 嵌套查询
? 嵌套查询概述
? 嵌套查询分类
? 嵌套查询求解方法
? 引出子查询的谓词
嵌套查询 (续 )
? 嵌套查询概述
– 一个 SELECT-FROM-WHERE语句称为一个
查询块
– 将一个查询块嵌套在另一个查询块的
WHERE子句或 HAVING短语的条件中的查
询称为嵌套查询
嵌套查询 (续 )
SELECT Sname 外层查询 /父查询
FROM Student
WHERE Sno IN
( SELECT Sno 内层查询 /子查询
FROM SC
WHERE Cno= ' 2 ');
嵌套查询 (续 )
– 子查询的限制
? 不能使用 ORDER BY子句
– 层层嵌套方式反映了 SQL语言的结构化
– 有些嵌套查询可以用连接运算替代
嵌套查询分类
? 不相关子查询
子查询的查询条件不依赖于父查询
? 相关子查询
子查询的查询条件依赖于父查询
嵌套查询求解方法
? 不相关子查询
是由里向外逐层处理。即每个子查询在
上一级查询处理之前求解,子查询的结果
用于建立其父查询的查找条件。
嵌套查询求解方法(续)
? 相关子查询
– 首先取外层查询中表的第一个元组,根据它与内层
查询相关的属性值处理内层查询,若 WHERE子句
返回值为真,则取此元组放入结果表;
– 然后再取外层表的下一个元组;
– 重复这一过程,直至外层表全部检查完为止。
引出子查询的谓词
? 带有 IN谓词的子查询
? 带有比较运算符的子查询
? 带有 ANY或 ALL谓词的子查询
? 带有 EXISTS谓词的子查询
一、带有 IN谓词的子查询
适于子查询返回结果是集合的情况。
[例 37] 查询与“刘晨”在同一个系学习的学生。
此查询要求可以分步来完成
① 确定“刘晨”所在系名
SELECT Sdept
FROM Student
WHERE Sname= ' 刘晨 ';
结果为:
Sdept
IS
带有 IN谓词的子查询(续)
② 查找所有在 IS系学习的学生。
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept= ' IS ';
结果为:
Sno Sname Sdept
95001 刘晨 IS
95004 张立 IS
构造嵌套查询
将第一步查询嵌入到第二步查询的条件中
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept IN
(SELECT Sdept
FROM Student
WHERE Sname= ‘ 刘晨 ’ );
此查询为不相关子查询。 DBMS求解该查询时也是分步
去做的。
带有 IN谓词的子查询(续)
用自身连接完成本查询要求
SELECT S1.Sno,S1.Sname,S1.Sdept
FROM Student S1,Student S2
WHERE S1.Sdept = S2.Sdept AND
S2.Sname = '刘晨 ';
带有 IN谓词的子查询(续)
父查询和子查询中的表均可以定义别名
SELECT Sno,Sname,Sdept
FROM Student S1
WHERE S1.Sdept IN
(SELECT Sdept
FROM Student S2
WHERE S2.Sname= ‘ 刘晨 ’ );
带有 IN谓词的子查询(续)
[例 38]查询选修了课程名为“信息系统”的学生学号和姓

SELECT Sno,Sname ③ 最后在 Student关系中
FROM Student 取出 Sno和 Sname
WHERE Sno IN
(SELECT Sno ② 然后在 SC关系中找出选
FROM SC 修了 3号课程的学生学号
WHERE Cno IN
(SELECT Cno ① 首先在 Course关系中找出“信
FROM Course 息系统”的课程号,结果为 3号
WHERE Cname= ‘信息系统’ ));
带有 IN谓词的子查询(续)
结果:
Sno Sname
---- -----
95001 李勇
95002 刘晨
带有 IN谓词的子查询(续)
– 用连接查询
SELECT Sno,Sname
FROM Student,SC,Course
WHERE Student.Sno = SC.Sno AND
SC.Cno = Course.Cno AND
Course.Cname=‘信息系统’;
二、带有比较运算符的子查询
● 当能确切知道内层查询返回单值时,可
用比较运算符( >,<,=,>=,<=,!=
或 < >)。
? 与 ANY或 ALL谓词配合使用
带有比较运算符的子查询(续)
例:假设一个学生只可能在一个系学习,并且必
须属于一个系,则在 [例 37]可以 用 = 代替 IN,
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept =
(SELECT Sdept
FROM Student
WHERE Sname= ‘ 刘晨 ’ );
带有比较运算符的子查询(续)
子查询一定要跟在比较符之后
错误 的例子:
SELECT Sno,Sname,Sdept
FROM Student
WHERE ( SELECT Sdept
FROM Student
WHERE Sname= ‘ 刘晨 ’ )
= Sdept;
【 例 】 查询志愿填报西安交通大学的考生考号 。
SELECT Exno
FROM Ewill
WHERE Scode1 =
( SELECT Scode1
FROM School
WHERE Scname=′西安交通大学 ′)
本查询的执行过程是,先执行子查询, 在表
School中查得西安交通大学学校代码 300; 然后执行
父查询, 在表 Ewill中根据志愿填报学校代码为 300
查得考生考号 。 显然, 子查询的结果用于父查询建
立查询条件 。
三、带有 ANY或 ALL谓词的子查询
谓词语义
– ANY:只要与子查询中一个值符合即可
– ALL:要与子查询中所有值相符合
带有 ANY或 ALL谓词的子查询(续)
需要配合使用比较运算符
> ANY 大于子查询结果中的某个值
> ALL 大于子查询结果中的所有值
< ANY 小于子查询结果中的某个值
< ALL 小于子查询结果中的所有值
>= ANY 大于等于子查询结果中的某个值
>= ALL 大于等于子查询结果中的所有值
<= ANY 小于等于子查询结果中的某个值
<= ALL 小于等于子查询结果中的所有值
= ANY 等于子查询结果中的某个值
=ALL 等于子查询结果中的所有值(通常没有实际意义)
!=(或 <>) ANY 不等于子查询结果中的某个值
!=(或 <>) ALL 不等于子查询结果中的任何一个值
带有 ANY或 ALL谓词的子查询(续)
[例 39] 查询其他系中比信息系任意 一 个 (其中某
一 个 )学生年龄小的学生姓名和年龄
SELECT Sname,Sage
FROM Student
WHERE Sage < ANY (SELECT Sage
FROM Student
WHERE Sdept= ' IS ')
AND Sdept <> ' IS ' ;
/* 注意这是父查询块中的条件 */
带有 ANY或 ALL谓词的子查询(续)
结果
Sname Sage
王敏 18
执行过程
1.DBMS执行此查询时,首先处理子查询,找出
IS系中所有学生的年龄,构成一个集合 (19,18)
2,处理父查询,找所有不是 IS系且年龄小于
19 或 18的学生
带有 ANY或 ALL谓词的子查询(续)
● ANY和 ALL谓词有时可以用集函数实现
– ANY与 ALL与集函数的对应关系
= <>或 != < <= > >=
ANY IN -- <MAX <=MAX >MIN >= MIN
ALL -- NOT IN <MIN <= MIN >MAX >= MAX
带有 ANY或 ALL谓词的子查询(续)
– 用集函数实现子查询通常比直接用 ANY或
ALL查询效率要高,因为前者通常能够减
少比较次数
带有 ANY或 ALL谓词的子查询(续)
[例 39']:用集函数实现 [例 39]
SELECT Sname,Sage
FROM Student
WHERE Sage <
(SELECT MAX(Sage)
FROM Student
WHERE Sdept= ' IS ')
AND Sdept <> ' IS ’;
带有 ANY或 ALL谓词的子查询(续)
[例 40] 查询其他系中比信息系 所有 学生年龄 都 小
的学生姓名及年龄。
方法一:用 ALL谓词
SELECT Sname,Sage
FROM Student
WHERE Sage < ALL
(SELECT Sage
FROM Student
WHERE Sdept= ' IS ')
AND Sdept <> ' IS ’;
查询结果为空表。
带有 ANY或 ALL谓词的子查询(续)
方法二:用集函数
SELECT Sname,Sage
FROM Student
WHERE Sage <
(SELECT MIN(Sage)
FROM Student
WHERE Sdept= ' IS ')
AND Sdept <>' IS ’;
四、带有 EXISTS谓词的子查询
1,EXISTS谓词
2,NOT EXISTS谓词
3,不同形式的查询间的替换
4,相关子查询的效率
5,用 EXISTS/NOT EXISTS实现全称量词
6,用 EXISTS/NOT EXISTS实现逻辑蕴函
带有 EXISTS谓词的子查询 (续)
● 1,EXISTS谓词
– 存在量词 ?
– 带有 EXISTS谓词的子查询不返回任何数据,只产生
逻辑真值, true”或逻辑假值, false”。
● 若内层查询结果非空,则返回真值
● 若内层查询结果为空,则返回假值
– 由 EXISTS引出的子查询,其目标列表达式通常都用
*,因为带 EXISTS的子查询只返回真值或假值,给
出列名无实际意义
● 2,NOT EXISTS谓词
? 这类子查询的求解方式与前面是不同的 (一般来
说, 子查询都在其父查询处理前求解 )。 在这里,
子查询的查询条件往往依赖于其父查询的某属
性值 。 这类查询称为相关子查询 。
? 求执行相关子查询的过程为:从外查询的关系
(Employee)中依次取一个元组, 根据它的值在
内查询进行检查, 若 WHERE子句为真, 将此
元组放入结果表 (为假, 则舍去 )。 这样反复处
理, 直至外查询关系的元组全部处理完为止 。
带有 EXISTS谓词的子查询 (续)
[例 41] 查询所有选修了 1号课程的学生姓名。
– 用嵌套查询
思路分析:
● 本查询涉及 Student和 SC关系。
● 在 Student中依次取每个元组的 Sno值,用此值去
检查 SC关系。
● 若 SC中存在这样的元组,其 Sno值等于此
Student.Sno值,并且其 Cno= '1',则取此
Student.Sname送入结果关系。
带有 EXISTS谓词的子查询 (续)
SELECT Sname
FROM Student
WHERE EXISTS
(SELECT *
FROM SC /*相关子查询 */
WHERE Sno=Student.Sno AND
Cno= ' 1 ');
求解过程
带有 EXISTS谓词的子查询 (续)
– 用连接运算
SELECT Sname
FROM Student,SC
WHERE Student.Sno=SC.Sno AND
SC.Cno= '1';
【 例 】 查询所有填写第一重点院校志愿代码
为 300,考分大于 600的考生姓名, 考号 。
SELECT Exname,Exno
FROM Examinee
WHERE Exgrade> 600
AND EXISTS
( SELECT * FROM Ewill
WHEREScode1=′300′AND
Examinee.Exno=Ewill.Exno)
带有 EXISTS谓词的子查询 (续)
[例 42] 查询没有选修 1号课程的学生姓名 。
SELECT Sname
FROM Student
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE Sno = Student.Sno
AND Cno='1');
此例用连接运算难于实现
带有 EXISTS谓词的子查询 (续)
3,不同形式的查询间的替换
一些 带 EXISTS或 NOT EXISTS谓词的子查询不能被其他
形式的子查询等价替换
所有 带 IN谓词、比较运算符,ANY和 ALL谓词的子查询
都能用带 EXISTS谓词的子查询等价替换。
带有 EXISTS谓词的子查询 (续)
例,[例 37]查询与“刘晨”在同一个系学习的学
生。 可以用带 EXISTS谓词的子查询替换:
SELECT Sno,Sname,Sdept
FROM Student S1
WHERE EXISTS
(SELECT *
FROM Student S2
WHERE S2.Sdept = S1.Sdept AND
S2.Sname = ‘ 刘晨 ’ );
带有 EXISTS谓词的子查询 (续)
5.用 EXISTS/NOT EXISTS实现全称量词 (难点 )
– SQL语言中没有全称量词 ? ( For all)
– 可以把带有全称量词的谓词转换为等价的带有
存在量词的谓词:
(?x)P ≡ ? (? x(? P))
带有 EXISTS谓词的子查询 (续)
[例 43] 查询选修了全部课程的学生姓名 。
SELECT Sname
FROM Student
WHERE NOT EXISTS
( SELECT *
FROM Course
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE Sno= Student.Sno
AND Cno= Course.Cno) ;
带有 EXISTS谓词的子查询 (续)
6,用 EXISTS/NOT EXISTS实现逻辑蕴函 (难点 )
– SQL语言中没有蕴函 (Implication)逻辑运算
– 可以利用谓词演算将逻辑蕴函谓词等价转换
为:
p ?q ≡ ? p∨ q
带有 EXISTS谓词的子查询 (续)
[例 44] 查询至少选修了学生 95002选修的全部
课程的学生号码。
解题思路:
● 用逻辑蕴函表达:查询学号为 x的学生,对所有的课程
y,只要 95002学生选修了课程 y,则 x也选修了 y。
● 形式化表示:
用 P表示谓词, 学生 95002选修了课程 y”
用 q表示谓词, 学生 x选修了课程 y”
则上述查询为, (?y) p ? q
带有 EXISTS谓词的子查询 (续)
● 等价变换:
(?y)p ? q ≡ ? (?y (?(p ? q ))
≡ ? (?y (?(? p∨ q)
≡ ??y(p∧ ?q)
● 变换后语义:不存在这样的课程 y,学生 95002
选修了 y,而学生 x没有选。
带有 EXISTS谓词的子查询 (续)
● 用 NOT EXISTS谓词表示,
SELECT DISTINCT Sno
FROM SC SCX
WHERE NOT EXISTS
(SELECT *
FROM SC SCY
WHERE SCY.Sno = ' 95002 ' AND
NOT EXISTS
(SELECT *
FROM SC SCZ
WHERE SCZ.Sno=SCX.Sno AND
SCZ.Cno=SCY.Cno));
3.3 查 询
3.3.1 概述
3.3.2 单表查询
3.3.3 连接查询
3.3.4 嵌套查询
3.3.5 集合查询
3.3.6 小结
3.3.5 集合查询
标准 SQL直接支持的集合操作种类
并操作 (UNION)
一般商用数据库支持的集合操作种类
并操作 (UNION)
交操作 (INTERSECT)
差操作 (MINUS)
1,并操作
? 形式
<查询块 >
UNION
<查询块 >
– 参加 UNION操作的各结果表的列数必须相同;
对应项的数据类型也必须相同
并操作(续)
[例 45] 查询计算机科学系的学生及年龄不大于 19
岁的学生。
方法一:
SELECT *
FROM Student
WHERE Sdept= 'CS'
UNION
SELECT *
FROM Student
WHERE Sage<=19;
并操作(续)
方法二:
SELECT DISTINCT *
FROM Student
WHERE Sdept= 'CS' OR Sage<=19;
并操作(续)
[例 46] 查询选修了课程 1或者选修了课程 2的学生。
方法一:
SELECT Sno
FROM SC
WHERE Cno=' 1 '
UNION
SELECT Sno
FROM SC
WHERE Cno= ' 2 ';
并操作(续)
方法二:
SELECT DISTINCT Sno
FROM SC
WHERE Cno=' 1 ' OR Cno= ' 2 ';
并操作(续)
[例 47] 设数据库中有一教师表 Teacher(Tno,
Tname,...)。查询学校中所有师生的姓名。
SELECT Sname
FROM Student
UNION
SELECT Tname
FROM Teacher;
new
2,交操作
标准 SQL中没有提供集合交操作,但可用
其他方法间接实现。
2,交操作
[例 48] 查询计算机科学系的学生与年龄不大于 19
岁的学生的交集
本例实际上就是查询计算机科学系中年龄不大于
19岁的学生
SELECT *
FROM Student
WHERE Sdept= 'CS' AND
Sage<=19;
交操作(续)
[例 49] 查询选修课程 1的学生集合与选修课程 2的
学生集合的交集
本例实际上是查询既选修了课程 1又选修了课程 2
的学生
SELECT Sno
FROM SC
WHERE Cno=' 1 ' AND Sno IN
(SELECT Sno
FROM SC
WHERE Cno=' 2 ');
交操作(续)
[例 50] 查询学生姓名与教师姓名的交集
本例实际上是查询学校中与教师同名的学生姓名
SELECT DISTINCT Sname
FROM Student
WHERE Sname IN
(SELECT Tname
FROM Teacher);
new
3,差操作
标准 SQL中没有提供集合差操作,但可用
其他方法间接实现。
3,差操作
[例 51] 查询计算机科学系的学生与年龄不大于 19
岁的学生的差集。
本例实际上是查询计算机科学系中年龄大于 19
岁的学生
SELECT *
FROM Student
WHERE Sdept= 'CS' AND
Sage>19;
差操作(续)
[例 52] 查询学生姓名与教师姓名的差集
本例实际上是查询学校中未与教师同名的学生
姓名
SELECT DISTINCT Sname
FROM Student
WHERE Sname NOT IN
(SELECT Tname
FROM Teacher); new
4,对集合操作结果的排序
? ORDER BY子句只能用于对最终查询结
果排序,不能对中间结果排序
? 任何情况下,ORDER BY子句只能出现
在最后
? 对集合操作结果排序时,ORDER BY子
句中用数字指定排序属性
new
对集合操作结果的排序(续)
[例 53] 错误写法
SELECT *
FROM Student
WHERE Sdept= 'CS'
ORDER BY Sno
UNION
SELECT *
FROM Student
WHERE Sage<=19
ORDER BY Sno; new
对集合操作结果的排序(续)
正确写法
SELECT *
FROM Student
WHERE Sdept= 'CS'
UNION
SELECT *
FROM Student
WHERE Sage<=19
ORDER BY 1;
new
3.3.6 SELECT语句的一般格式
SELECT [ALL|DISTINCT]
<目标列表达式 > [别名 ] [, <目标列表达式 > [别名 ]] …
FROM <表名或视图名 > [别名 ]
[, <表名或视图名 > [别名 ]] …
[WHERE <条件表达式 >]
[GROUP BY <列名 1>[,<列名 1’>],..
[HAVING <条件表达式 >]]
[ORDER BY <列名 2> [ASC|DESC]
[,<列名 2’> [ASC|DESC] ] … ] ;
目标列表达式
? 目标列表达式格式
(1) [ <表名 >.] *
(2) [<表名 >.]<属性列名表达式 >[,[<表名 >.]<属性列
名表达式 >] …
<属性列名表达式 >:由 属性列,作用于属性列的 集函
数 和 常量 的任意算术运算( +,-,*,/)组成的运
算公式。
集函数格式
COUNT
SUM
AVG ([DISTINCT|ALL] <列名 >)
MAX
MIN
COUNT ([DISTINCT|ALL] *)
条件表达式格式
( 1)
<属性列名 >
<属性列名 > θ <常量 >
[ANY|ALL] (SELECT语句 )
条件表达式格式
( 2)
<属性列名 > <属性列名 >
<属性列名 > [NOT] BETWEEN <常量 > AND <常量 >
(SELECT (SELECT
语句 ) 语句 )
条件表达式格式
( 3) (<值 1>[,<值 2> ] …)
<属性列名 > [NOT] IN
(SELECT语句 )
条件表达式格式
(4) <属性列名 > [NOT] LIKE <匹配串 >
(5) <属性列名 > IS [NOT] NULL
(6) [NOT] EXISTS (SELECT语句 )
条件表达式格式
( 7) AND AND
<条件表达式 > <条件表达式 > <条件表达 > …
OR OR