SQL子查询

一、子查询基础知识

子查询是一个嵌套在 Select、Insert、Update 或 Delete 语句或其他子查询中的查询。任何允许使用表达式的地方都可以使用子查询。在以下示例中,子查询在 Select 语句中被用作名为 MaxUnitPrice 的列表达式。

Select ord.SalesOrderID, ord.OrderDate,
    (Select MAX(OrdDet.UnitPrice)
     FROM AdventureWorks.Sales.SalesOrderDetail AS ordDet
     Where ord.SalesOrderID = ordDet.SalesOrderID) AS MaxUnitPrice
FROM AdventureWorks.Sales.SalesOrderHeader AS ord

子查询也称为内部查询或内部选择,而包含子查询的语句也称为外部查询或外部选择。

许多包含子查询的 Transact-SQL 语句都可以改用联接表示。其他问题只能通过子查询提出。在 Transact-SQL 中,包含子查询的语句和语义上等效的不包含子查询的语句在性能上通常没有差别。但是,在一些必须检查存在性的情况中,使用联接会产生更好的性能。否则,为确保消除重复值,必须为外部查询的每个结果都处理嵌套查询。所以在这些情况下,联接方式会产生更好的效果。以下示例显示了返回相同结果集的 Select 子查询和 Select 联接:

/* Select statement built using a subquery. */
Select Name
FROM AdventureWorks.Production.Product
Where ListPrice =
    (Select ListPrice
     FROM AdventureWorks.Production.Product
     Where Name = 'Chainring Bolts' )

/* Select statement built using a join that returns
   the same result set. */
Select Prd1. Name
FROM AdventureWorks.Production.Product AS Prd1
     JOIN AdventureWorks.Production.Product AS Prd2
       ON (Prd1.ListPrice = Prd2.ListPrice)
Where Prd2. Name = 'Chainring Bolts'

嵌套在外部 Select 语句中的子查询包括以下组件:

●包含常规选择列表组件的常规 Select 查询。
●包含一个或多个表或视图名称的常规 FROM 子句。
●可选的 Where 子句。
●可选的 GROUP BY 子句。
●可选的 HAVING 子句。

子查询的 Select 查询总是使用圆括号括起来。它不能包含 COMPUTE 或 FOR BROWSE 子句,如果同时指定了 TOP 子句,则只能包含 orDER BY 子句。

子查询可以嵌套在外部 Select、Insert、Update 或 Delete 语句的 Where 或 HAVING 子句内,也可以嵌套在其他子查询内。尽管根据可用内存和查询中其他表达式的复杂程度的不同,嵌套限制也有所不同,但嵌套到 32 层是可能的。个别查询可能不支持 32 层嵌套。任何可以使用表达式的地方都可以使用子查询,只要它返回的是单个值。

如果某个表只出现在子查询中,而没有出现在外部查询中,那么该表中的列就无法包含在输出(外部查询的选择列表)中。

包含子查询的语句通常采用以下格式中的一种:

●Where e­xpression [NOT] IN (subquery)
●Where e­xpression comparison_operator [ANY | ALL] (subquery)
●Where [NOT] EXISTS (subquery)

在某些 Transact-SQL 语句中,子查询可以作为独立查询来计算。从概念上说,子查询结果会代入外部查询(尽管这不一定是 Microsoft SQL Server 2005 实际处理带有子查询的 Transact-SQL 语句的方式)。

有三种基本的子查询。它们是:

●在通过 IN 或由 ANY 或 ALL 修改的比较运算符引入的列表上操作。
●通过未修改的比较运算符引入且必须返回单个值。
●通过 EXISTS 引入的存在测试。

二、子查询类型

1.带in的嵌套查询

select emp.empno,emp.ename,emp.job,emp.sal from scott.emp where sal in (select sal from scott.emp where ename=''WARD'');

上述语句完成的是查询薪水和WARD相等的员工,也可以使用not in来进行查询。

2.带any的嵌套查询

select emp.empno,emp.ename,emp.job,emp.sal from scott.emp where sal >any(select sal from scott.emp where job=''MANAGER'');

等价于下边两步的执行过程:
(1)执行“select sal from scott.emp where job=''MANAGER''”
(2)查询到3个薪水值2975、2850和2450,父查询执行下列语句:
select emp.empno,emp.ename,emp.job,emp.sal from scott.emp where sal >2975 or sal>2850 or sal>2450;

3.带some的嵌套查询

select emp.empno,emp.ename,emp.job,emp.sal from scott.emp where sal =some(select sal from scott.emp where job=''MANAGER'');

等价于下边两步的执行过程:
(1)子查询,执行“select sal from scott.emp where job=''MANAGER''”。
(2)父查询执行下列语句。
select emp.empno,emp.ename,emp.job,emp.sal from scott.emp where sal =2975 or sal=2850 or sal=2450;

l 带【any】的嵌套查询和【some】的嵌套查询功能是一样的。早期的SQL仅仅允许使用【any】,后来的版本为了和英语的【any】相区分,引入了【some】,同时还保留了【any】关键词。

4.带all的嵌套查询

select emp.empno,emp.ename,emp.job,emp.sal from scott.emp where sal >all(select sal from scott.emp where job=''MANAGER'');

等价于下边两步的执行过程:
(1)子查询,执行“select sal from scott.emp where job=''MANAGER''”。
(2)父查询执行下列语句。
select emp.empno,emp.ename,emp.job,emp.sal from scott.emp where sal >2975 and sal>2850 and sal>2450;

5.带exists的嵌套查询

select emp.empno,emp.ename,emp.job,emp.sal from scott.emp,scott.dept where exists (select * from scott.emp where scott.emp.deptno=scott.dept.deptno);

6.并操作的嵌套查询

并操作就是集合中并集的概念。属于集合A或集合B的元素总和就是并集。
(select deptno from scott.emp) union (select deptno from scott.dept);

7.交操作的嵌套查询

交操作就是集合中交集的概念。属于集合A且属于集合B的元素总和就是交集。
(select deptno from scott.emp) intersect (select deptno from scott.dept);

8.差操作的嵌套查询

差操作就是集合中差集的概念。属于集合A且不属于集合B的元素总和就是差集。
(select deptno from scott.dept) minus (select deptno from scott.emp);

l 并、交和差操作的嵌套查询要求属性具有相同的定义,包括类型和取值范围。

三、应用举例



上一篇: 恢复"显示所有文件或文件夹"选项
下一篇: 参数查询
文章来自: 网络
引用通告: 查看所有引用 | 我要引用此文章
Tags:
最新日志:
评论: 1 | 引用: 0 | 查看次数: 5589
发表评论
登录后再发表评论!