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频道,一旦我们在楼梯上发布一个新的级别,就会得到通知!

时间: 2024-10-06 09:18:12

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

通往t - sql的阶梯:超越基本级别6:使用CASE表达式和IIF函数

摘要:此文章转自: http://www.sqlservercentral.com/articles/Stairway+Series/108723/ Stairway to T-SQL: Beyond The Basics Level 6: Using the CASE Expression and IIF Function 通往t - sql的阶梯:超越基本级别6:使用CASE表达式和IIF函数 By Gregory Larsen, 2016/04/20 (first published: 2

楼梯T-SQL:超越基础水平3:建立一个相关子查询

Gregory Larsen,2014 / 03 / 05 该系列              本文是系列的一部分:楼梯楼梯T-SQL:超越基础              下面就从他的楼梯T-SQL DML.Gregory Larsen覆盖的T-SQL语言如子查询更先进的方面.              在这楼梯2级我讨论如何在Transact-SQL语句中使用子查询.这楼梯水平将扩大对查询主题的讨论类型的查询称为相关子查询.我将探讨什么是相关子查询以及它是如何不同于普通的子查询.此外,我将提供你

相关子查询【SQL Server】

查询book表中大于该类图书价格平均值的图书信息 先将第一条记录的类编号的值为2代入子查询中,子查询为 select avg(price) from book b where b.id=2 则得到类编号为2的书籍平均价格为(23+45)/2=34 再和外部查询做判断 select * from book a where price>34 然后再类编号为3的书籍中,再次通过比较 相关子查询(多值子查询) 1.非相关子查询(嵌套子查询)是独立于外部的子查询,子查询只会执行一次,相关查询可以执行多次,

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

SQLServer子查询可以分为 相关子查询 和 嵌套子查询 两类.前提, 假设Books表如下: 类编号 图书名 出版社 价格 -------------------------------------------------------- 2 c#高级应用 圣通出版 23.00 2 Jsp开发应用 机械出版社 45.00 3 高等数学 济南出版社 25.00 3 疯狂英语 清华大学出版社 32.00 嵌套子查询的执行不依赖与外部的查询. 执行过程: (1)执行子查询,其结果不被显示,而是传递

SQL Server进阶(十四)常用函数

FOR XML PATH 利用 T-sql 的从句 for xml path('') 实现多行合并到一行, 并带有分隔符 https://blog.csdn.net/rav009/article/details/50723307 SELECT ',' + au.UserCode FROM dbo.AcceptanceUser au FOR XML PATH ('') SELECT STUFF((SELECT ',' + au.UserCode FROM dbo.AcceptanceUser au

在SQL Server中为什么不建议使用Not In子查询

原文:在SQL Server中为什么不建议使用Not In子查询     在SQL Server中,子查询可以分为相关子查询和无关子查询,对于无关子查询来说,Not In子句比较常见,但Not In潜在会带来下面两种问题: 结果不准确 查询性能低下       下面我们来看一下为什么尽量不使用Not In子句.   结果不准确问题     在SQL Server中,Null值并不是一个值,而是表示特定含义,其所表示的含义是"Unknow",可以理解为未定义或者未知,因此任何与Null值

SQL语句汇总(终篇)—— 表联接与联接查询

既然是最后一篇那就不能只列出些干枯的标准语句,更何况表联接也是SQL中较难的部分,所以此次搭配题目来详细阐述表联接. 上一篇博文说到相关子查询效率低下,那我们怎么能将不同表的信息一起查询出来呢?这就需要用到表联接. 和之前的UNION组合查询不同,UNION是将不同的表组合起来,也就是纵向联接,说白了就是竖着拼起来. 而表联接是通过笛卡尔乘积将表进行横向联接,所谓的通过笛卡尔乘积简单说就是两表的行依次相联再相加.要想更详细的理解可以百度下,毕竟本文主要是汇总SQL语句. 现在有如下两张表: 这是

SQL SERVER 2008 数据库隔离级别代码演示

SQL SERVER 2008 数据库隔离级别代码演示 ? 在各种SQL 的教程上一直都强调SQL SERVER 的4个隔离级别(其实这是SQL 工业标) 未提交读 ReadUncommited? 已提交读 ReadCommited? 不可重复读 RepeatableRead? 序列化 Serializable (为什么叫这个么名字?) 这4种隔离级别,本身没有优劣之分,完全取决于应用的场景. 本质上,他们是在 隔离性(紊乱程度) 和 灵活性(并发性) 之间博弈.简单的说,灵活性越高,隔离性越差

SQL Server索引内部结构:SQL Server索引的阶梯级别10

作者David Durant,2012年1月20日 该系列 本文是"Stairway系列:SQL Server索引的阶梯"的一部分 索引是数据库设计的基础,并告诉开发人员使用数据库关于设计者的意图.不幸的是,当性能问题出现时,索引往往被添加为事后考虑.这里最后是一个简单的系列文章,应该使他们快速地使任何数据库专业人员"快速" 在之前的水平上,我们采取了合理的方法来指标,重点是他们能为我们做些什么.现在是时候采取物理方法,检查指标的内部结构;了解索引的内部特性导致了对