子查询是指一条SELECT语句作为另一条SELECT语句的一部分,外层的SELCT语句称为外部查询,内层的SELECT语句称为内部查询(或子查询)。子查询分两种:嵌套子查询和相关子查询。
1.嵌套子查询
嵌套子查询的执行不依赖于外部嵌套。
嵌套子查询的执行过程为:首先执行子查询,子查询得到的结果集不被显示出来,而是传给外部查询,作为外部查询的条件使用,然后执行外部查询,并显示查询结果。子查询可以多层嵌套。
嵌套子查询一般也分为两种:子查询返回单个值和子查询返回一个值列表。
(1)返回单个值,该值被外部查询的比较操作(如,=、!=、、>=)使用,该值可以使子查询中使用集合函数得到的值。 【例30】查询所有价格高于平均价格的书。
use pubs go select title from titles where price>
(select averageprice=avg(price)
from titles) 执行结果为:
title
------------------
The Busy Executive\'s Database Guide Straight Talk About Computers Silicon Valley Gastronomic Treats But Is It User Friendly? Secrets of Silicon Valley Computer Phobic AND Non-Phobic Individuals: Behavior Variations Prolonged Data Deprivation: Four Case Studies Onions, Leeks, and Garlic: Cooking Secrets of the Mediterranean Sushi, Anyone?
(所影响的行数为 9 行)
在这个例子中,SQL Server首先获得“select averageprice=avg(price) from titles”的结果集,该结果集为单行单列,然后将其作为外部查询的条件执行外部查询,并得到最终的结果。 【例31】查询书号为pc1035的作者的作者号、作者姓名。
use pubs go
select au_id,au_lname,au_fname from authors where au_id=(select au_id
from titleauthor where title_id=\'pc1035\' ) 得到的结果为:
au_id
au_lname
au_fname
----------- --------- -------------------- 238-95-7766
Carson
Cheryl
(所影响的行数为 1 行) 例31的查询也可以用前面讲过的表连接来实现,代码如下:
use pubs go
select authors.au_id,au_lname,au_fname from authors,titleauthor where authors.au_id=titleauthor.au_id and title_id=\'pc1035\' 得到的结果与例2使用子查询一样,但连接操作要比子查询快,所以能使用表连接的时候应尽量使用表连接。
(2)返回一个值列表,该列表被外部查询的IN、NOT IN、ANY或ALL比较操作使用。 IN表示属于,即外部查询中用于判断的表达式的值与子查询返回的值列表中的一个值相等;NOT IN表示不属于。
【例32】查询所有出版了书的作者的信息。
use pubs go select au_id,au_lname,au_fname
from authors
where au_id in
(select au_id
from titleauthor) 得到的结果为:
au_id au_lname au_fname ----------- --------- -------------------- 172-32-1176 White Johnson 213-46-8915 Green Marjorie 238-95-7766 Carson Cheryl 267-41-2394 O\'Leary Michael „„
(所影响的行数为 19 行)
在这个例子中,子查询的结果集不是单行单列,而是多行单列。 【例33】查询没有出版书的作者的信息。
use pubs go select au_id,au_lname,au_fname
from authors
where au_id not in
(select au_id
from titleauthor) 查询结果为:
au_id au_lname au_fname ----------- --------- -------------------- 527-72-3246 Greene Morningstar 893-72-1158 McBadden Heather 341-22-1782 Smith Meander 724-08-9931 Stringer Dirk
(所影响的行数为 4 行)
ANY、SOME和ALL用于一个值与一组值的比较,以“>”为例,ANY 表示大于一组值中的任意一个,ALL表示大于一组值中的每一个。比如,>ANY(1,2,3)表示大于1;而>ALL(1,2,3)表示大于3。SOME在SQL-92标准中与ANY含义相同。 2.相关子查询
在相关子查询中,子查询的执行依赖于外部查询,多数情况下是子查询的WHERE子句中引用了外部查询的表。
相关子查询的执行过程与嵌套子查询完全不同,嵌套子查询中子查询只执行一次,而相关子查询中的子查询需要重复地执行。相关子查询的执行过程如下:
(1)子查询为外部查询的每一行执行一次,外部查询将子查询引用的列的值传给子查询。 (2)如果子查询的任何行与其匹配,外部查询就返回结果行。 (3)再回到第一步,直到处理完外部表的每一行。 例如:查找销售量大于平均销售量的书的书号、书名。
select title_id from sales s1 where qty > (select avg(qty) from sales s2 where s1.title_id=s2.title_id) 得到结果如下:
title_id -------- BU1032 MC3021 PS2091
(所影响的行数为 3 行)
与下面的程序比较一下:
select title_id from sales where qty > (select avg(qty) from sales) 运行结果为:
TITLE_ID -------- PC8888 PS2091 TC3218 MC3021 PS2106 PS7777 BU2075 BU1111 PC1035
(所影响的行数为 9 行)
3.在查询的基础上创建新表
使用SELECT INTO语句可以在查询的基础上创建新表,SELECT INTO语句首先创建一个新表,然后用查询的结果填充新表。 语法格式为: SELECT 列 INTO 新表 FROM 源表
[WHERE 条件1] [GROUP BY 表达式1] [HAVING 条件2] [ORDER BY 表达式2[ASC|DESC]] 例如:建立一个新表B_TITLEAUTHOR,内容为商业类书的情况。
select title,price,au_fname,au_lname into b_titleauthor from titles t join titleauthor ta
on (t.title_id=ta.title_id )
join authors a
on (a.au_id=ta.au_id) where type=\'busine\' 执行结果为:
(所影响的行数为 6 行) select * from b_titleauthor 得到的结果为:
title price au_fname au_lname ------------------ --------------------- -------------------- The Busy Executive\'s Database Guide 19.9900 Marjorie Green The Busy Executive\'s Database Guide 19.9900 Abraham Bennet Cooking with Computers: Surreptitious Balance Sheets 11.9500 Michael O\'Leary Cooking with Computers: Surreptitious Balance Sheets 11.9500 Stearns MacFeather You Can Combat Computer Stre! 2.9900 Marjorie Green Straight Talk About Computers 19.9900 Dean Straight
(所影响的行数为 6 行)