T-SQL的进阶:超越基本级别3:构建相关子查询——701小组
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小组的更多相关文章
- [SQL SERVER系列]之嵌套子查询和相关子查询
子查询有两种类型,一种是只返回一个单值的子查询,这时它可以用在一个单值可以使用的地方,这时子查询可以看作是一个拥有返回值的函数:另外一种是返回一列值的子查询,这时子查询可以看作是一个在内存中临时存在的 ...
- sql之独立子查询和相关子查询总结
1.独立子查询:顾名思义:就是子查询和外层查询不存在任何联系,是独立于外层查询的: 下面就看一个例子: 有一张订单表 Sales.Order 和一张 客户表 Sales.Customer 下面的sql ...
- SQL相关子查询是什么?和嵌套子查询有什么区别?
目录 两者的各种叫法 相关子查询MySQL解释 相关子查询Wikipedia解释 相关子查询执行步骤拆解 相关子查询和嵌套查询的区别 参考资料 两者的各种叫法 相关子查询叫做:Correlated S ...
- 相关子查询【SQL Server】
查询book表中大于该类图书价格平均值的图书信息 先将第一条记录的类编号的值为2代入子查询中,子查询为 select avg(price) from book b where b.id=2 则得到类编 ...
- sql 相关子查询
子查询:嵌套在其他查询中的查询. 子查询有称内部查询,而包含子查询的语句称之为外部查询 所有的子查询可以分两类,既 相关子查询和非相关子查询 1>非相关子查询是独立于外部查询的子查询,子查询总共 ...
- 相关子查询和嵌套子查询 [SQL Server]
SQLServer子查询可以分为 相关子查询 和 嵌套子查询 两类.前提,假设Books表如下: 类编号 图书名 出版社 价格-------------- ...
- SQL嵌套子查询和相关子查询的执行过程有什么区别(推荐)
SQLServer子查询可以分为 相关子查询 和 嵌套子查询 两类.前提, 假设Books表如下: 类编号 图书名 出版社 价格 ----------------------------------- ...
- 2.SQL语言进阶
0.实验数据 表1.course表 表2.student表 表3.sc表 1.SQL连接 内连接 select * from student,sc where student.sno=sc.sno;/ ...
- SQL Server进阶 窗口函数
概述 设计窗口函数目的? 在开窗函数出现之前存在着很多用 SQL 语句很难解决的问题,很多都要通过复杂的相关子查询或者存储过程来完成. 为了解决这些问题,在 2003 年 ISO SQL 标准加入了 ...
随机推荐
- C# TextBlock 上标
我需要做一个函数,显示 ,但是看起来用 TextBlock 做的不好看. 我用 WPF 写的上标看起来不好看,但是最后有了一个简单方法让他好看. 本文告诉大家如何做一个好看的上标. 一开始做的方法: ...
- 上传代码 CodePlex
博客园作为博客备份,博客会更新一份在博客园 CodePlex是微软开源项目网站,有很多人都在上面传代码,我们也可以上传自己的代码 注册 我们可以用微软账号注册,填写用户名.密码,很快就好. 新建项目 ...
- [mysql使用(2)] mysql的一些语法与Oracle的差别
一.表空间 mysql的表空间有共享表空间和独占表空间,独占表空间,其实就是一张表一个表空间,其实也就是一张表一个数据文件,共享表空间似乎有点类似oracle的表空间,不同的表可以保存在同一个数据文件 ...
- python去除读取文件中多余的空行
今天在写登录程序练习的时候,黑名单文件中多了几行空行.导致运行的时候报错:IndexError: list index out of range 代码 brackData = open(brackDa ...
- JS中的单引号和双引号
JS里面的单引号和双引号可以同时使用,但是要遵循一定的准则. 最外面用了双引号了,那么里面就不能再用双引号了,因为引号是成双对的,浏览器读到一个双引号后,到第2个双引号时才算结束:同理,浏览器读到一个 ...
- 值得学习的C/C++开源框架(转)
值得学习的C语言开源项目 - 1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的 ...
- C++中引用的底层实现
为了研究一下C++中引用的底层实现,写了一个小代码验证其中的基本原理. 引用是一个变量的别名,到底会不会为引用申请内存空间?如果申请空间,空间存放的是什么,下面的代码就主要解决这个疑问. 代码如下,详 ...
- Solitaire
Solitaire Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
- ASP.NET Core的身份认证框架IdentityServer4(1)-特性一览
IdentityServer4是ASP.NET Core的一个包含OpenID和OAuth 2.0协议的框架.OpenID和OAuth 的区别请看 https://www.zhihu.com/ques ...
- 【Kafka源码】KafkaController启动过程
[TOC] 之前聊过了很多Kafka启动过程中的一些加载内容,也知道了broker可以分为很多的partition,每个partition内部也可以分为leader和follower,主从之间有数据的 ...