在 SELECT 查询中使用子查询

  子查询(或称嵌套查询)是一个嵌套在 SELECT、INSERT、UPDATE 或 DELETE 语句或其他子查询中的查询。子查询中还可以嵌套子查询,最多嵌套32层。

  任何允许使用表达式的地方都可以使用子查询。

  子查询也称为内部查询(或内部SELECT),而包含子查询的语句也称为外部查询(或外部SELECT)。子查询的结果集被用于外部查询。


一、使用子查询的场景

  可以在许多位置指定子查询,以下是常见的情形:

1. 使用别名的子查询

  子查询和外部查询可以引用同一表,为了使查询语句清晰易懂,子查询应使用显式别名。

SELECT e1.StateProvinceID, e1.AddressID

FROM Address AS e1

WHERE e1.AddressID IN

  ( SELECT e2.AddressID

    FROM Address AS e2

    WHERE e2.StateProvinceID = 39 )


  大部分的子查询都可以改写成联接。例如,上例可以改为自联接。

SELECT e1.StateProvinceID, e1.AddressID

FROM Address AS e1

 INNER JOIN Address AS e2

   ON e1.AddressID = e2.AddressID

   AND e2.StateProvinceID = 39;


2. 使用 IN 或 NOT IN 的子查询

  此类子查询将在外部查询中排除某些子集。

SELECT Name

FROM Product

WHERE ProductSubcategoryID NOT IN

  ( SELECT ProductSubcategoryID

    FROM ProductSubcategory

    WHERE Name = 'Mountain Bikes' OR Name = 'Road Bikes' )


3. 使用比较运算符的子查询

  子查询可以由一个比较运算符(=、< >、>、> =、<、! >、! < 或 < =)引入。

SELECT CustomerID

FROM Customer

WHERE TerritoryID =

  ( SELECT TerritoryID

    FROM SalesPerson

    WHERE BusinessEntityID = 276 )


  在子查询中还可以使用分组和聚集函数。例如:

SELECT Name

FROM Product

WHERE ListPrice >

  ( SELECT MIN (ListPrice)

    FROM Product

    GROUP BY ProductSubcategoryID

    HAVING ProductSubcategoryID = 14 )


4. 使用 ANY、SOME 或 ALL 的子查询

  可以用 ALL 或 ANY 关键字修改引入子查询的比较运算符。SOME 是与 ANY 等效的 ISO 标准。

通过修改的比较运算符引入的子查询返回零个值或多个值的列表,并且可以包括 GROUP BY 或 HAVING 子句。这些子查询可以用 EXISTS 重新表述。

SELECT Name

FROM Product

WHERE ProductSubcategoryID =ANY

   (SELECT ProductSubcategoryID

    FROM ProductSubcategory

    WHERE Name = 'Wheels') ;


5. 使用 EXISTS 或 NOT EXISTS 的子查询

  使用 EXISTS 关键字引入子查询后,子查询的作用就相当于进行存在测试。外部查询的 WHERE 子句测试子查询返回的行是否存在。子查询实际上不产生任何数据,它只返回 TRUE 或 FALSE 值。

SELECT Name

FROM Product

WHERE EXISTS

  ( SELECT *

    FROM ProductSubcategory

    WHERE ProductSubcategoryID =

           ProductSubcategoryID

       AND Name = 'Wheels' )


6. 替代表达式的子查询

  在 T-SQL 中,除了在 ORDER BY 列表中以外,在 SELECT、UPDATE、INSERT 和 DELETE 语句中任何能够使用表达式的地方都可以用子查询替代。

SELECT Name, ListPrice,

(SELECT AVG(ListPrice) FROM Product) AS Average,

   ListPrice - (SELECT AVG(ListPrice) FROM Product)

   AS Difference

FROM Product

WHERE ProductSubcategoryID = 1;



二、子查询的类型

1. 自包含子查询(Self-contained subquery)

  在包含自包含子查询的查询中,自包含子查询是独立于其所隶属的外部查询的,因此自包含查询是可以独立运行的,此类子查询也称为独立子查询。


2. 相关子查询(Correlated subquery)

  在包含相关子查询(也称为重复子查询)的查询中,子查询依靠外部查询获得值。

  在下例中,外部查询逐个选择 SalesOrderDetail(即 s1)的行。子查询为外部查询中的选择计算正在考虑的每个销售的平均数量。对于每个可能的 s1 值,如果数量小于计算的平均值,SQL Server 将计算子查询并将所考虑的记录放入结果中。

SELECT ProductID, OrderQty

FROM SalesOrderDetail s1

WHERE s1.OrderQty <

   (SELECT AVG (s2.OrderQty)

    FROM SalesOrderDetail s2

    WHERE s2.ProductID = s1.ProductID)



三、子查询的常见问题

1. 注意区分标量(Scalar)子查询与多值(Multi-valued)子查询

  标量子查询仅返回单个的值,而多值子查询返回多个值。

  在下例中,如果子查询返回单个值,则运行此查询时不会发生错误。如果子查询返回多个值,则查询将失败。

SELECT e1.StateProvinceID, e1.AddressID

FROM Address AS e1

WHERE e1.AddressID =

  ( SELECT e2.AddressID

    FROM Address AS e2

    WHERE e2.StateProvinceID = 39 )


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值