sql - 无法理解运行聚合的工作原理

标签 sql sql-server

首先让我给你介绍一个例子,然后我会问这个问题。 代码

SELECT
    orderyear
   ,qty
FROM
    Sales.OrderTotalsByYear;

给我一​​张看起来像这样的表格

orderyear   qty
----------- -----------
2007        25489
2008        16247
2006        9581

我需要返回每年的订单年份、数量和历年的运行总量。也就是说,对于每一年,返回直到那一年的数量总和。因此,对于 View 中记录的最早年份(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;

还有一张 table

orderyear   qty         runqty
----------- ----------- -----------
2006        9581        9581
2007        25489       35070
2008        16247       51317

现在,我了解这段代码的作用,但我不了解它的方式。我在过程和面向对象编程方面有经验,但这让我发疯。 如果查询以这样的方式进行

  1. FROM
  2. WHERE
  3. GROUP BY
  4. HAVING
  5. SELECT
  6. ORDER BY

那么它是如何利用内部和外部 SELECT 之间的关系将内部 SELECT 与外部 SELECT 结合起来的呢?外部 SELECT 是否先运行并在遇到表中的第一个元素时停止,然后内部 SELECT 开始运行 O2.orderyear <= O1.orderyear 为真的元素?还是发生了完全不同的事情?

最佳答案

逻辑上,对于系统生成的每一行(通过FROMWHEREGROUP BYHAVING),系统将评估 SELECT 子句。作为每一行评估的一部分,系统将评估相关的子查询:

(
    SELECT
        SUM(O2.qty)
    FROM
        Sales.OrderTotalsByYear AS O2
    WHERE
        O2.orderyear <= O1.orderyear
)

使用当前行的 O1.orderyear 值。

但是,从实用的角度来看1,系统可能能够优化其对该子查询的评估。一个足够聪明的优化器,如果统计数据表明值得这样做,可能会决定按 orderyear 顺序评估外部查询,并创建一个已排序的 OrderTotalsByYear 表的副本按 orderyear 顺序(或使用已经表示此排序顺序的索引)。在这种情况下,系统将能够评估此子查询结果,而无需为外部查询的每一行重新扫描整个 OrderTotalsByYear 表。

优化器做什么只能通过获取执行计划来确定,并且取决于您的特定表 - 它们的结构、索引和其中包含的数据。


1SQL 是根据逻辑 处理顺序定义的。实现可以自由地以与逻辑处理顺序不同的顺序执行操作,前提是它们产生的结果与遵循逻辑处理顺序时所获得的结果相同2。通常,SQL 也被定义为处理集合,而不是指定逐行或从左到右处理。

2SQL Server 在这里采取了比它应有的更多的自由,并且可能会产生错误,而这些错误如果它遵循逻辑处理顺序就不会产生。呵呵。

关于sql - 无法理解运行聚合的工作原理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40524059/

相关文章:

sql - Microsoft Access - 为什么要输入参数值?

mysql - 连接三个 MySQL 表并从一个表中获取最大值

mysql - 使用崩溃后添加到备份的数据更新数据库

sql-server - 目标主体名称不正确。无法生成 SSPI 上下文

sql - 将表的行扩展/拆分为更多行

mysql - 合并 2 个 MySQL 数据转储的最佳方法是什么?

php - 实现 Mult 的更好方法。 PHP 中 1 篇文章的类别?

Java JDBC ActiveDirectoryAuthentication Azure SQLServer 失败并出现 401/adfs/services/trust/13/windowstransport 异常

sql-server - SSIS:从 SQL 到数据流任务的变量

sql-server - 如何跨多个表强制执行 CHECK 约束