Sql Server系列:嵌套查询

  嵌套查询是指一个查询语句嵌套在另一个查询语句内部的查询。嵌套查询也就子查询,在SELECT子句中先计算子查询,子查询结果作为外层另一个查询的过滤条件,查询可以基于一个表或多个表。子查询中可以使用比较运算符,如“<”、“<=”、“>”、“>=”等。

  子查询中常用的操作符有ANY(SOME)、ALL、EXISTS。子查询可以添加到SELECT 、UPDATE和DELETE语句中,可以进行多层嵌套。

1 使用比较运算符

  子查询使用比较运算符,如“<”、“<=”、“>”、“>=”等。

  示例:返回单个值的SELECT语句的嵌套查询

SELECT * FROM [dbo].[Product]
WHERE [UnitPrice] = (
    SELECT MIN([UnitPrice]) FROM [dbo].[Product]
)
SELECT * FROM [dbo].[Product]
WHERE [CategoryID] = 
( SELECT [CategoryID] FROM [dbo].[Category] WHERE [CategoryName] = 'LINQ to SQL' )

2. 使用IN关键字

  IN关键字进行子查询时,内层查询语句仅仅返回一个数据列,这个数据列里的值将提供给外层查询语句进行比较。

  示例:返回多个值的子查询的嵌套查询

SELECT * FROM [dbo].[Product]
WHERE [CategoryID] IN (
    SELECT [CategoryID] FROM [dbo].[Category] WHERE [CategoryID] <= 10
)

  尽管使用IN的嵌套查询方式可以实现,但更好的方式是使用内连接实现这种查询,而不是使用使用嵌套的SELECT。

  上例的子查询使用INNER JOIN方式:

SELECT [dbo].[Product].* FROM [dbo].[Product]
INNER JOIN [dbo].[Category]
    ON [dbo].[Product].[CategoryID] = [dbo].[Category].[CategoryID]
WHERE [dbo].[Category].[CategoryID] <= 10

  出于性能方面的考虑,如果没有特别的理由要使用嵌套的SELECT,则还是应使用连接方式作为默认的解决方案。在大部分情况下,SQL Server会将嵌套子查询解决方案解析为和使用连接用于的查询计划,在检查嵌套子查询和内连接查询计划时,会发现它们的完全相同的计划。大多数情况下,这两种方法没有多大的区别。当查询计划不同时,连接通常的更好的选择。

  SELECT语句中可以使用NOT IN运算符,其作用与IN相反。

3. ANY、SOME关键字

  ANY和SOME关键字是同义词,表示满足其中任一条街。它们允许创建一个表达式对子查询的返回值列表进行比较,只要满足内层子查询中任何一个比较条件,就返回一个结果作为外层查询的条件。

  ANY关键字接在一个比较操作符的后面,表示与子查询返回的任何值比较为TRUE,则返回TRUE。

  示例:

IF 20 > ANY ( SELECT [UnitsInStock] FROM [dbo].[Product] )
    PRINT '1'
ELSE
    PRINT '0'

4. ALL关键字

  ALL关键字用于需要同时满足所有内层查询的条件,只有当子查询返回的所有值比较都为TRUE,才返回TRUE。

  示例:

IF 20 > ALL ( SELECT [UnitsInStock] FROM [dbo].[Product] )
    PRINT '1'
ELSE
    PRINT '0'

5. EXISTS关键字

  EXISTS关键字后面的参数是一个任意的子查询,系统对子查询进行运算以判断它是否返回行,如果至少返回一行,则EXISTS的结果为TRUE,此时外层查询语句将进行查询;如果子查询没有返回任何行,那么EXISTS返回的结果是FALSE,此时外层语句将不进行查询。

  示例:

SELECT * FROM [dbo].[Category]
WHERE EXISTS (
    SELECT * FROM [dbo].[Product]
    WHERE [CategoryID] = 1
)

  EXISTS关键字还可以和条件表达式一起使用。

SELECT * FROM [dbo].[Category]
WHERE [CategoryName] ='LINQ to SQL'
AND EXISTS (
    SELECT * FROM [dbo].[Product]
    WHERE [CategoryID] = 1
)

  NOT EXISTS与EXISTS使用方法相同,返回的结果相反。

SELECT * FROM [dbo].[Category]
WHERE NOT EXISTS (
    SELECT * FROM [dbo].[Product]
    WHERE [CategoryID] = 1
)

  Exists关联子查询:查询所有存在Product的Category

SELECT * FROM [dbo].[Category] c
WHERE EXISTS (
    SELECT * FROM [dbo].[Product] p
    WHERE p.[CategoryID] = c.[CategoryID]
)

  上例同样可以使用INNER JOIN实现:

SELECT c.* FROM [dbo].[Category] c
INNER JOIN [dbo].[Product] p
    ON p.[CategoryID] = c.[CategoryID]

  基于连接的语法可以得到相同的结果,但使用EXISTS具有更好的性能。使用EXISTS关键字,SQL Server不需要执行一行一行的完全连接,而是直接寻找记录,直到找到第一个匹配的记录。

posted @ 2014-12-01 09:31  libingql  阅读(20002)  评论(0编辑  收藏  举报