T-SQL的进阶:超越基本级别3:构建相关子查询

格雷戈里·拉森,2014/03/05

原文链接:

http://www.sqlservercentral.com/articles/Stairway+Series/105972/

该系列

这篇文章是进阶系列的一部分: t - sql的进阶:超越基础

从他的阶梯到T-SQL DML,Gregory Larsen涵盖了T-SQL语言的更高级的方面,如子查询。

在这个楼梯的第二层,我讨论了如何在Transact - T-SQL语句中使用子查询。这个楼梯级别将通过讨论一种称为关联子查询的子查询类型来扩展子查询主题。我将探讨什么是相关子查询,以及它与普通子查询的区别。此外,我还将为您提供一些超越基础的Transaction- T-SQL语句示例,并使用关联子查询来帮助识别结果集中返回的行,以满足复杂的业务需求。

什么是相关子查询?

在这个楼梯的第2级,我们了解到正常的子查询只是在另一个Transact - SQL语句内的一个SELECT语句,在这个语句中子查询如果独立于外部查询而返回结果。关联子查询是子查询的一种形式,它不能独立于外部查询运行,因为它包含来自外部查询的一个或多个列。相关子查询,就像普通的子查询,有时被称为内部查询。如果相关子查询(内部查询)独立于外部查询运行,则它将返回一个错误。因为内部查询的执行依赖于来自外部查询的值,因此它被称为相关子查询。

相关子查询可以执行很多次。它将为在外部查询中选择的每个候选行运行一次。每个候选行的列值将用于为关联子查询的每次执行的内部的外部查询列提供值。包含相关子查询的语句的最终结果将基于相关子查询的每次执行的结果。

相关子查询示例的示例数据

为了演示如何使用相关子查询,我需要一些测试数据。我的所有示例都将使用AdventureWorks2008R2数据库,而不是创建自己的测试数据。如果你想跟随并运行在您的环境中我的例子你可以从这里下载AdventureWorks2008R2数据库:http://msftdbprodsamples.codeplex.com/releases/view/93587

WHERE子句中关联子查询的示例

为了演示在WHERE子句中使用关联子查询,我想要确定这些CustomerID在单个订单中购买了超过70个项目。为了达到这个要求,我可以运行清单1中的代码。

清单1:在WHERE子句中关联子查询

当我运行清单1中的代码时,我得到了报告1中的输出。

报告1:运行清单1中的代码时返回的结果

如果您回顾清单1中的代码,您将看到我使用相关子查询限制了我的位置。子查询是圆括号中的代码,我从清单1中提取了相关的子查询代码,并将其放入清单2中。

清单2:清单1中的子查询代码

如果我运行清单2中的代码,我将发现在报告2中显示了一个错误。

报告2:在清单2中运行代码时出错

我得到了报告2中显示的错误,因为关联子查询包含对列的引用。SalesOrderID,它是来自外部查询的一列。由于所有相关子查询从外部查询引用一个或多个列,因此不能独立地运行与它关联的外部查询。不能独立于整个Transact - SQL语句运行子查询的事实是将相关子查询与普通子查询区分开来。

这里给出的示例是在WHERE子句中使用相关子查询的一个非常简单的例子。希望通过这样一个简单的示例,它很容易理解普通子查询和相关子查询之间的区别。通常,一个相关的子查询可能要复杂得多。此外,请记住,在不使用相关子查询的情况下,可能还有其他方法来满足您的业务需求。

正如您所看到的,编写一个相关子查询非常类似于普通子查询,但是您不能独立地运行相关子查询。

HAVING子句中关联子查询的示例

有时,您可能想要从外部查询中限制一个有不同值的子句。这时,您可以在您的“有”子句中使用相关子查询。假设您必须编写一个查询,该查询将计算那些在2008年税前购买价值超过15万美元的产品的客户的回扣金额。清单3中的代码通过在HAVING子句中使用关联子查询来计算这些值客户的回扣金额。

清单3:有子句的相关子查询

当我运行清单5中的代码时,我得到了报告3中的结果。

报告3:运行清单3的结果

清单3中的相关子查询代码在关联子查询中的外部查询中使用GROUP BY子句中的CustomerID。关联子查询将对从GROUP BY子句返回的每一行执行一次。这允许“有”子句通过对每个SalesOrderHeader记录的SubTotal列的值求和来计算销售给每个CustomerID的产品总量,其中记录与来自外部查询的CustomerID相关联。清单3中的transact - sql语句只返回了CustomerID已经购买超过15万美元的产品的一行。

包含相关子查询的UPDATE语句的示例

相关子查询不仅可以使用SELECT语句返回结果集。您还可以使用它们来更新SQL Server表中的数据。为了演示这一点,我首先使用清单4中的代码在tempdb表中生成一些测试数据。

清单4:创建和填充测试表的代码

清单4中的代码创建了一个CarInventory表,然后填充了8行,表示当前库存的汽车。

销售经理周期性地使用清单5中的查询来查看他的InvoicePriceRatio。

清单5:InvoicePriceRatio查询

当经理运行此查询时,她注意到有许多类似的汽车,其发票金额相同,有不同的InvoicePriceRatio值。为了最大限度地提高她的发票价格,她要求她支持编写一个查询,以更新她所有汽车上的StickerPrice,这样每辆车都有相同的CarName值,就有相同的InvoicePriceRatio。她希望IT人员将StickerPrice设置为与CarName的最大价格相同的值。这样,所有具有相同CarName值的汽车将具有相同的StickerPrice值。为了完成CarInventory表的更新,IT人员运行清单6中的Transact - SQLl语句,其中包含一个相关子查询。

清单6:相关子查询,以更新CarInventory以最大价格

清单8中的代码使用关联子查询中的外部查询的CarName来标识每个惟一的CarName的最大StickerPrice。然后,在相关子查询中发现的最大StickerPrice值用于更新具有相同名称的每个CarInventory记录的StickerPrice值。

相关子查询的性能考虑

在编写包含相关子查询的Transact - SQL语句时,应该注意一些性能方面的考虑。当外部查询包含少量行时,性能并不差。但是,当外部查询包含大量的行时,从性能的角度来看,它的伸缩性并不好。这是因为要对外部查询中的每个候选行执行相关的子查询。因此,当外部查询包含越来越多的候选行时,一个相关的子查询必须多次执行,因此Transact - SQL语句将需要更长的时间运行。如果您发现相关子查询Transact - SQL语句的性能不符合您的要求,那么您应该寻找替代解决方案,例如使用内部或外部连接操作的查询,或者从外部查询返回少量候选行的查询。

摘要

关联子查询是一个内部查询,它包含来自外部查询的一个或多个列。关联子查询对外部查询的每个候选行执行一次。因为关联子查询包含来自外部查询的列,因此它不能独立于外部查询运行。相关子查询有它们的位置,尽管在外部查询中识别出大量候选行时,从性能角度看,它们的伸缩性并不好。

问题和答案

在本节中,您可以通过回答以下问题来回顾您如何理解相关子查询的概念。

问题1:

在编写相关子查询时,需要有___________________。(填入空白)

来自内部查询的一个或多个列,用于约束相关子查询的结果。

在相关子查询的选择列表中使用的内部查询中的一个或多个列。

来自外部查询的一个或多个列,用于约束相关子查询的结果。

在相关子查询的选择列表中使用的外部查询的一个或多个列。

问题2:

选择所有关于相关子查询的语句。

随着候选行的数量增加,包含相关子查询的Transact - SQL语句的性能得到了提高。

相关子查询将对来自外部查询的每个候选行执行一次。

相关子查询将引用内部查询中的一个或多个列。

当在一个拥有子句中使用相关子查询时,将对由GROUP by子句返回的每个候选行执行一次内部查询。

问题3:

相关子查询与普通子查询类似,而相关子查询可以独立于整个Transact - SQL语句(True或False)运行。

真正的

答案:

问题1:

正确答案是c .相关子查询需要在相关子查询语句中使用外部查询中的一个或多个列。在执行相关子查询时,这些外部列引用将替换为每个候选行的值。

问题2:

正确的答案是b和d . a是不正确的,因为随着候选行数量的增加,相关子查询的执行次数增加,而Transact - SQL语句性能变得更糟。c是不正确的,因为相关子查询必须包含来自外部查询的一个或多个行,而不是内部查询。

问题3:

正确的答案是b .如果您尝试独立于完整的Transact - SQL语句运行相关子查询,那么相关的子查询语句将会失败。

这篇文章是T - SQL的进阶的一部分:除了基本的楼梯

注册到我们的RSS频道,一旦我们在楼梯上发布一个新的级别,就会得到通知!

T-SQL的进阶:超越基本级别3:构建相关子查询——701小组的更多相关文章

  1. [SQL SERVER系列]之嵌套子查询和相关子查询

    子查询有两种类型,一种是只返回一个单值的子查询,这时它可以用在一个单值可以使用的地方,这时子查询可以看作是一个拥有返回值的函数:另外一种是返回一列值的子查询,这时子查询可以看作是一个在内存中临时存在的 ...

  2. sql之独立子查询和相关子查询总结

    1.独立子查询:顾名思义:就是子查询和外层查询不存在任何联系,是独立于外层查询的: 下面就看一个例子: 有一张订单表 Sales.Order 和一张 客户表 Sales.Customer 下面的sql ...

  3. SQL相关子查询是什么?和嵌套子查询有什么区别?

    目录 两者的各种叫法 相关子查询MySQL解释 相关子查询Wikipedia解释 相关子查询执行步骤拆解 相关子查询和嵌套查询的区别 参考资料 两者的各种叫法 相关子查询叫做:Correlated S ...

  4. 相关子查询【SQL Server】

    查询book表中大于该类图书价格平均值的图书信息 先将第一条记录的类编号的值为2代入子查询中,子查询为 select avg(price) from book b where b.id=2 则得到类编 ...

  5. sql 相关子查询

    子查询:嵌套在其他查询中的查询. 子查询有称内部查询,而包含子查询的语句称之为外部查询 所有的子查询可以分两类,既 相关子查询和非相关子查询 1>非相关子查询是独立于外部查询的子查询,子查询总共 ...

  6. 相关子查询和嵌套子查询 [SQL Server]

    SQLServer子查询可以分为 相关子查询 和 嵌套子查询 两类.前提,假设Books表如下: 类编号  图书名         出版社               价格-------------- ...

  7. SQL嵌套子查询和相关子查询的执行过程有什么区别(推荐)

    SQLServer子查询可以分为 相关子查询 和 嵌套子查询 两类.前提, 假设Books表如下: 类编号 图书名 出版社 价格 ----------------------------------- ...

  8. 2.SQL语言进阶

    0.实验数据 表1.course表 表2.student表 表3.sc表 1.SQL连接 内连接 select * from student,sc where student.sno=sc.sno;/ ...

  9. SQL Server进阶 窗口函数

    概述  设计窗口函数目的? 在开窗函数出现之前存在着很多用 SQL 语句很难解决的问题,很多都要通过复杂的相关子查询或者存储过程来完成. 为了解决这些问题,在 2003 年 ISO SQL 标准加入了 ...

随机推荐

  1. 如何结合场景利用block进行回调

    我们在开发中常常会用到函数回调,你可以用通知来替代回调,但是大多数时候回调是比通知方便的,所以何乐而不为呢?如果你不知道回调使用的场景,我们来假设一下: 1.我现在玩手机 2.突然手机没有电了 3.我 ...

  2. Codeforces Round #441 (Div. 2, by Moscow Team Olympiad) D. Sorting the Coins

    http://codeforces.com/contest/876/problem/D 题意: 最开始有一串全部由"O"组成的字符串,现在给出n个数字,指的是每次把位置n上的&qu ...

  3. CoreCLR源码探索(七) JIT的工作原理(入门篇)

    很多C#的初学者都会有这么一个疑问, .Net程序代码是如何被机器加载执行的? 最简单的解答是, C#会通过编译器(CodeDom, Roslyn)编译成IL代码, 然后CLR(.Net Framew ...

  4. 简述static关键字、void与void *(void指针)、函数指针

    static关键字1.修饰局部变量,延长局部变量的生命周期.使变量成为静态局部变量,在编译时就为变量分配内存,直到程序退出才释放存储单元.2.修饰全局变量,限制全局变量的使用范围为本文件中.全局变量默 ...

  5. win10 uwp 弹起键盘不隐藏界面元素

    本文主要讲,在我们使用手机输入的时候,会因为手机的虚拟键盘隐藏了一些界面的元素.我们有一个简单的方法让虚拟键盘不隐藏界面元素. 我们需要的界面元素是在显示了虚拟键盘后的空间能全部显示,如果不能的话,还 ...

  6. 如何通过写bat 安装Windows服务,本人亲测成功

    1. 安装的bat文件 @echo on color 2f mode con: cols=80 lines=25 @echo 请按任意键开始安装后台服务... pause cd /d %~dp0 Le ...

  7. Python 之简单线程池创建

    try: from Queue import Queue, Empty except: from queue import Queue, Empty import threading import t ...

  8. Java基础笔记11

    异常: 即java程序在运行时出现的意外情况.  java如何处理异常. try{ //可能发生异常的地方 }catch(异常类型 对象){  //异常处理处 }catch(异常类型 对象){ }.. ...

  9. 哈尔滨理工大学第六届程序设计团队 I-Team

    /* 以前做过一个插队的题,这个类似从后往前操作 */ #include <iostream> #include <stdio.h> #include <algorith ...

  10. Group(), Groups(),& Groupdict()

    group() 返回一个或多个匹配的字串.如果只有一个参数,结果只有单个字符串:如果有多个参数,结果是一个元组,元组里每一项对应一个参数.没有参数,group1默认是0(整个匹配串被返回).如果gro ...