zoukankan      html  css  js  c++  java
  • 子查询 总结

    子查询是一个嵌套在 SELECT、INSERT、UPDATE 或 DELETE 语句或其他子查询中的查询。任何允许使用表达式的地方都可以使用子查询。

    子查询类型

    • (1)使用别名。
    • (2)使用 IN 或 NOT IN。
    • (3)在 UPDATE、DELETE 和 INSERT 语句中。
    • (4)使用比较运算符。
    • (5)使用 ANY、SOME 或 ALL。
    • (6)使用 EXISTS 或 NOT EXISTS。
    • (7)代替表达式。
    • (1)在通过 IN 或由 ANY 或 ALL 修改的比较运算符引入的列表上操作。
    • (2)通过未修改的比较运算符引入且必须返回单个值。
    • (3)通过 EXISTS 引入的存在测试。
    • WHERE expression [NOT] IN (subquery)
    • WHERE expression comparison_operator [ANY | ALL] (subquery)
    • WHERE [NOT] EXISTS (subquery)

    对子查询的限制:

    • (1)通过比较运算符引入的子查询选择列表只能包括一个表达式或列名称(对 SELECT * 执行的 EXISTS 或对列表执行的 IN 子查询除外)。
    • (2)如果外部查询的 WHERE 子句包括列名称,它必须与子查询选择列表中的列是联接兼容的。
    • (3)ntext、text 和 image 数据类型不能用在子查询的选择列表中。
    • (4)由比较运算符(即后面未跟关键字 ANY 或 ALL 的运算符)引入的子查询不能包含 GROUP BY 和 HAVING 子句(因为必须返回单个值)。
    • (5)包含 GROUP BY 的子查询不能使用 DISTINCT 关键字。
    • (6)不能指定 COMPUTE 和 INTO 子句。
    • (7)只有指定了 TOP 时才能指定 ORDER BY。
    • (8)不能更新使用子查询创建的视图。
    • (9)由 EXISTS 引入的子查询的选择列表有一个星号 (*),而不是单个列名。因为由 EXISTS 引入的子查询创建了存在测试并返回 TRUE 或 FALSE 而非数据,所以其规则与标准选择列表的规则相同。
    • (10)子查询可以嵌套但最多不应超过32层嵌套

    子查询举例(例子来自msdn

    (1)使用别名(等价于自联接)

    子查询和外部查询引用同一表的语句称为自联接(将某个表与自身联接)

    例如,可以使用子查询查找与 Terri Duffy 具有相同经理的雇员:

    USE AdventureWorks;
    GO
    SELECT EmployeeID, ManagerID
    FROM HumanResources.Employee
    WHERE ManagerID IN
        (SELECT ManagerID
         FROM HumanResources.Employee
         WHERE EmployeeID = 12)
     可以使用表的别名以区别内外查询使用的表
    USE AdventureWorks;
    GO
    SELECT e1.EmployeeID, e1.ManagerID
    FROM HumanResources.Employee AS e1
    WHERE e1.ManagerID IN
        (SELECT e2.ManagerID
         FROM HumanResources.Employee AS e2
         WHERE e2.EmployeeID = 12)
    等价于下列的自连接语句
    USE AdventureWorks;
    GO
    SELECT e1.EmployeeID, e1.ManagerID
    FROM HumanResources.Employee AS e1
    INNER JOIN HumanResources.Employee AS e2
    ON e1.ManagerID = e2.ManagerID
    AND e2.EmployeeID = 12
    (2)使用 IN、NOT IN 的子查询

    通过 IN(或 NOT IN)引入的子查询结果是包含零个值或多个值的列表。子查询返回结果之后,外部查询将利用这些结果。

    下面的查询查找 Adventure Works Cycles 生成的所有车轮产品的名称。

    USE AdventureWorks;
    GO
    SELECT Name
    FROM Production.Product
    WHERE ProductSubcategoryID IN
        (SELECT ProductSubcategoryID
         FROM Production.ProductSubcategory
         WHERE Name = 'Wheels')
    等价的联接查询
    Use AdventureWorks;
    GO
    SELECT p.Name, s.Name
    FROM Production.Product p
    INNER JOIN Production.ProductSubcategory s
    ON p.ProductSubcategoryID = s.ProductSubcategoryID
    AND s.Name = 'Wheels'
    此类in的子查询,联接和子查询稍有不同。使用联接的时候可以再结果中显示多个表的列而子查询则只能显示外查询表中的列。
    (3)用 ANY、SOME 或 ALL 修改的比较运算符
    SOME 是与 ANY 等效的 SQL-92 标准。 =ANY 运算符与 IN 等效   < >ANY 运算符则不同于 NOT IN   < >ALL 与 NOT IN 等效

    以 > 比较运算符为例,>ALL 表示大于每一个值(它表示大于最大值)。>ANY 表示至少大于一个值(即大于最小值)。

    下例查找定价高于或等于任何产品子类别的最高定价的产品

    USE AdventureWorks;
    GO
    SELECT Name
    FROM Production.Product
    WHERE ListPrice >= ANY
        (SELECT MAX (ListPrice)
         FROM Production.Product
         GROUP BY ProductSubcategoryID)
    (4)使用 EXISTS 的子查询

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

    使用 EXISTS 引入的子查询的语法如下:

    WHERE [NOT] EXISTS (subquery)

    以下查询将查找 Wheels 类别中所有产品的名称:

    USE AdventureWorks;
    GO
    SELECT Name
    FROM Production.Product
    WHERE EXISTS
        (SELECT * 
         FROM Production.ProductSubcategory
         WHERE ProductSubcategoryID = 
                Production.Product.ProductSubcategoryID
            AND Name = 'Wheels')

    (5)用于替代表达式的子查询

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

    以下示例说明如何使用此增强功能。此查询找出所有山地车产品的价格、平均价格以及两者之间的差价。

    USE AdventureWorks;
    GO
    SELECT Name, ListPrice, 
    (SELECT AVG(ListPrice) FROM Production.Product) AS Average, 
        ListPrice - (SELECT AVG(ListPrice) FROM Production.Product)
        AS Difference
    FROM Production.Product
    WHERE ProductSubcategoryID = 1
    (6)相关子查询

    相关子查询(也称为重复子查询)的查询中,子查询依靠外部查询获得值。这意味着子查询是重复执行的,为外部查询可能选择的每一行均执行一次。SQL Server 通过将每一行的值代入内部查询

    此查询在 SalesPerson 表中检索奖金为 5000 且雇员标识号与 EmployeeSalesPerson 表中的标识号相匹配的雇员的名和姓的一个实例。

    USE AdventureWorks;
    GO
    SELECT DISTINCT c.LastName, c.FirstName 
    FROM Person.Contact c JOIN HumanResources.Employee e
    ON e.ContactID = c.ContactID 
    WHERE 5000.00 IN
    (SELECT Bonus
    FROM Sales.SalesPerson sp
    WHERE e.EmployeeID = sp.SalesPersonID) ;
    GO

    该语句中前面的子查询无法独立于外部查询进行计算。它需要 Employee.EmployeeID 值,但是此值随 Microsoft SQL Server 2005 检查 Employee 中的不同行而改变。如何计算此查询:SQL Server 通过将每一行的值代入内部查询,考虑 Employee 表中的每一行是否都包括在结果中。例如,如果 SQL Server 首先检查 Syed Abbas 行,那么变量 Employee.EmployeeID 将取值 288,SQL Server 将该值代入内部查询。

    相关子查询还可以用于外部查询的 HAVING 子句中

    以下示例将查找最高标价超过其平均价格两倍的产品型号。

    USE AdventureWorks;
    GO
    SELECT p1.ProductModelID
    FROM Production.Product p1
    GROUP BY p1.ProductModelID
    HAVING MAX(p1.ListPrice) >= ALL
    (SELECT 2 * AVG(p2.ListPrice)
    FROM Production.Product p2
    WHERE p1.ProductModelID = p2.ProductModelID) ;
    GO
  • 相关阅读:
    贪婪与非贪婪模式
    Arduino语言介绍
    POJ 3249 记忆化搜索或拓扑排序
    POJ 3177 缩点 + 边双连通图
    POJ 1637 网络流构图
    hdu 1285 拓扑排序+优先队列
    POJ 3160 缩点+拓扑排序+简单dp
    POJ 3592 缩点+拓扑排序+最长路
    针对11级队员的暑假训练计划(初稿)
    POJ 2762 缩点+判断是否是最长链
  • 原文地址:https://www.cnblogs.com/dyufei/p/2573978.html
Copyright © 2011-2022 走看看