第八章、子查询
8.1、子查询入门
子查询包含两种类型:一种,只返回一个单值,相当于一个拥有返回值的函数
另一种,返回一列值得子查询,相当于一个临时的数据表。
8.1.1、单值子查询
与普通select没区别,唯一限制是子查询返回值必须只有一行记录,只有一个列:标量子查询。
select 1 as F1,2,(select min(FYearPublished) from T_book),(select max(FYearPublished) from T_book) as F4
8.1.2、列值子查询
可以返回一个多行多列的结果集:表子查询。
select T_Reader.FName,t2.FYearPublished,t2.FName from T_Reader,(select * from T_BOOK where FYearpublished<1800) t2
8.2、select列表中的标量子查询
标量子查询完全可以返回随当前查询记录而变化的值。
Attention:这里的子查询与前边讲的有所不同,前面的子查询没有依赖于外部查询中的字段,也就是可以直接单独执行,但是这里依赖于外部查询中的字段,这里子查询无法单独执行。
select FId,FName,
( select max(FyearPublished) from T_Book where T_Book.FCategoryId=T_Category.FId )
from T_Category
8.3、where子句中的标量子查询
select T_Category.FId , T_Book.FName , T_Book.FYearPublished
from T_Category Inner Join T_Book On T_Category.FId = T_Book.FCategoryId
where T_Book.FYearPublished =
(
select min (T_Book.FYearPublished) from T_Book where T_Book.FCategoryId = T_Category.FId
)
8.4、集合运算符与子查询
运算符:IN、Any、All、Exists
8.4.1、In运算符
In运算符可以用来匹配一个固定集合中的某一项,in后面也可以是子查询,不过必须与相匹配的的对应。
select * from T_Book where FYearPublished in (2001,2003,2005)
8.4.2、Any与Some
any必须与其他的比较运算符共同使用,而且必须将比较运算符放在any关键字之前,所比较的值需要匹配子查询中的任意一个值。"=any" 等价于 In 运算符,而"<>Any"则等价于Not In运算符。
select * from T_Reader where FYearPublished = Any
( select FYearPublished from T_Book )
any包括<,>,>=,<=等比较运算符的共同使用。
select * from T_Book where FYearPublished < Any
( select FYearOfBirth from T_Reader )
Attention:Any不能与固定的集合匹配, 如 > any (2001,2003)
8.4.3、All运算符
All运算符要求比较的值需要匹配子查询中的所有值。All运算符不能单独使用,必须和比较运算符共同使用。并且All不能与固定的集合相匹配。
Attention:当使用All时,如果带匹配的集合为空,也就是子查询没有返回任何数据的时候,不论与什么比较运算符搭配使用All的返回值将永远是true。
select * from T_Book
where FYearPublished < All ( select FYearOfJoin from T_Reader )
8.4.4、Exsits 运算符
Exists运算符是单目运算符,它不与列匹配,因此它也不要求待匹配的集合石单列。Exist运算符用来检查每一行是否匹配子查询,可以认为Exists就是用来测试子查询的结果是否为空,如果结果集为空,则匹配结果为false,否则匹配结果为true。
select * from T_Book
where exists ( select * from T_Reader where FProvince='ShanDong' )
使用Exists运算符要么就是匹配返回表中所有数据,要么就是不匹配不返回任何数据,好像Exists运算符没有什么意义,其实exists运算符真正意义只有和相关子查询一起使用才更有意义。
8.5、其他类型SQL语句中的子查询应用
子查询也可用在insert 、update、delete中。
8.5.1、子查询在Insert中应用
如果复制一个表的数据到另一个表,除了insert...values还有一种就是insert...select。
Insert into T_Reader2(FId,FName) select FId,FName from T_Reader
与此同时,Insert...select还可以将插入的数据进行处理以后再插入。如下,采用case函数来实现对数据插入前的处理。
insert into T_ReaderFavorite2(FCategoryId,FReaderId)
select FCategoryId,
(CASE
when FReaderId<=10 then FReaderId Else FReader - FCategoryId
End)
from T_ReaderFavorite
因为可以对数据进行处理,因此insert...select不受同结构表间的数据插入。
8.5.2、子查询在Update...set语句中的应用
主要是update与where相结合的使用。
update T_Book b1 set bi.FYearPubulished = 2005
where (select count(*) from T_Book b2 where b1.FCategoryId=b2.FcategoryId)>3
8.5.3、子查询在delete中使用
子查询delete中唯一可以应用的位置就是where子句。
delete from T_Book b1 where
(select count(*) from T_Book b2 where b1.FCategoryId=b2.FCategoryId)>3