首先让我向您介绍一个例子,之后我会问这个问题。 代码
SELECT
orderyear
,qty
FROM
Sales.OrderTotalsByYear;
给了我一个看起来像这样的表
orderyear qty
----------- -----------
2007 25489
2008 16247
2006 9581
我需要每年返回多年来的订单年份,数量和运行总量。也就是说,对于每年,返回到该年份的数量之和。因此,对于视图(2006年)中记录的最早年份,运行总数等于该年份的数量。第二年(2007年),运行总数是第一年加第二年的总和,依此类推。 代码看起来像这样
SELECT
orderyear
,qty
,(
SELECT
SUM(O2.qty)
FROM
Sales.OrderTotalsByYear AS O2
WHERE
O2.orderyear <= O1.orderyear
)
AS runqty
FROM
Sales.OrderTotalsByYear AS O1
ORDER BY
orderyear;
和一个表
orderyear qty runqty
----------- ----------- -----------
2006 9581 9581
2007 25489 35070
2008 16247 51317
现在,我明白了这段代码的作用,但我不明白 HOW 它做到了。我有程序和面向对象编程的经验,但这只会让我发疯。 如果查询以这样的方式进行
- FROM
- WHERE
- GROUP BY
- HAVING
- 选择
- ORDER BY
醇>
然后如何通过使用内部和外部SELECT之间的关系来设法将内部SELECT组合在外部SELECT中?外部SELECT首先运行,当它遇到表中的第一个元素时它会停止,然后内部SELECT开始运行 O2.orderyear&lt; = O1.orderyear 为真的元素吗?或者是否有一些完全不同的东西?
答案 0 :(得分:1)
逻辑,对于系统生成的每一行(通过FROM
,WHERE
,GROUP BY
和HAVING
),系统将评估SELECT
子句。作为每行评估的一部分,系统将评估相关子查询:
(
SELECT
SUM(O2.qty)
FROM
Sales.OrderTotalsByYear AS O2
WHERE
O2.orderyear <= O1.orderyear
)
使用当前行的O1.orderyear
值。
但是,从实用立场 1 ,系统可能能够优化其对此子查询的评估。足够聪明的优化器,如果统计数据表明它值得做,可能会决定以orderyear
顺序评估外部查询,并创建OrderTotalsByYear
表中的orderyear
表的副本。 order(或使用已经表示此排序顺序的索引)。在这种情况下,系统将能够评估此子查询结果,而无需为外部查询的每一行重新扫描整个OrderTotalsByYear
表。
优化程序所做的只能通过获取执行计划来确定,并且将取决于您的特定表 - 它们的结构,索引以及它们中包含的数据。
1 SQL是根据逻辑处理顺序定义的。实现可以按照与逻辑处理顺序不同的顺序执行操作,前提是它们产生的结果与逻辑处理顺序遵循 2 时获得的结果相同。通常,SQL也定义为处理集而不是指定逐行或从左到右的处理。
2 SQL Server在这里采取了比它应该更多的自由,并且可能产生错误,这些错误不会生成 它遵循逻辑处理顺序。哼哼。
答案 1 :(得分:0)
您可以通过两个步骤来考虑查询:select子句中的子查询是相关的,即它通过O2.orderyear <= O1.orderyear
引用主查询。因此主要查询被执行,并且对于从表中读取的每个单个记录(别名为O1),它执行子查询以获得运行数量。
因此,当主查询读取2008的记录时,它会执行
SELECT SUM(O2.qty)
FROM Sales.OrderTotalsByYear AS O2
WHERE O2.orderyear <= 2008
有两个记录,其中一年&lt; = 2008:2007和2008.他们的数量正在被添加,因此您可以获得与2008年记录一起显示的运行总计。 2007年和2009年的记录也是如此。最后,您的行是按顺序排列的,以便按升序显示年份。