5

empno 上具有聚集唯一索引的表结构。

CREATE TABLE [dbo].[EMP](
    [EMPNO] [int] NOT NULL,
    [ENAME] [varchar](10) NULL,
    [JOB] [varchar](9) NULL,
    [MGR] [int] NULL,
    [HIREDATE] [datetime] NULL,
    [SAL] [int] NULL,
    [COMM] [int] NULL,
    [DEPTNO] [int] NULL
) ON [PRIMARY]

询问

SELECT sal,sum(sal) over(PARTITION BY empno)
FROM emp

查询计划

在此处输入图像描述

4

2 回答 2

3

具有窗口聚合的计划通常使用公共子表达式假脱机。这种类型的计划的一个很好的写在这里是分区和公共子表达式假脱机

假设表有以下行

CREATE TABLE [dbo].[EMP](
    [EMPNO] [int] NOT NULL,
    [SAL] [int] NULL) 

INSERT INTO [dbo].[EMP] 
VALUES (1,1),
       (1,2), 
       (1,3),
       (1,4), 
       (2,1),
       (2,2)

它总共有 6 行,有 2 个不同的EMPNO值。显示实际发出的行数的实际执行计划如下。

在此处输入图像描述

计划顶部的段迭代器向通过它的行添加一个标志,指示它何时是新分区的开始(empno即已更改)。

紧靠其左侧的假脱机(主假脱机)一次从段迭代器中获取一行,并将其插入到 tempdb 中的工作表中。一旦它得到表明一个新组已经开始的标志,它就会向嵌套循环运算符的顶部输入返回一行。

这会导致在工作表中的行(计划中的辅助假脱机)上调用流聚合,SUM([SAL])然后计算此值与工作表中的行(计划中的第三个假脱机运算符)在工作表被截断,为新组做好准备。

主段线轴发出一个虚拟行以处理最终组,这就是为什么发出的实际行数显示为 3(组数加一)

于 2013-04-14T08:26:18.820 回答
0

带有子句的聚合函数OVER可以这样重写: FROM table AS x INNER JOIN (SELECT partition columns , AggregateWithoutOverClause(...) ... FROM ...) AS y ON x.PartitionColumns = y.PartitionColumns (如果分区列是强制性的- 非空)。

例子:

SET STATISTICS IO ON;
SET NOCOUNT ON;

-- OP's query
SELECT sal,sum(sal) over(PARTITION BY empno) 
FROM emp;

-- Reqwriten query
SELECT a.sal, b.SumSal
FROM emp a
INNER JOIN (SELECT EMPNO, SUM(sal) AS SumSal FROM emp GROUP BY EMPNO) b ON a.EMPNO = b.EMPNO;

结果:

sal         
----------- -----------
1           10
2           10
3           10
4           10
1           3
2           3

Table 'Worktable'. Scan count 3, logical reads 21, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'EMP'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

sal         SumSal
----------- -----------
1           10
2           10
3           10
4           10
1           3
2           3

Table 'Worktable'. Scan count 3, logical reads 21, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'EMP'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

执行计划: 在此处输入图像描述

这将仅解释最后一个 join在此处输入图像描述

第一次连接的解释可以在 Per-group processing / Partitioning and the Common Subexpression Spool部分找到。

于 2013-04-14T15:00:05.057 回答