这里我们有两个类似grouping sets
的查询,使用 whereSELECT
子句包含一些聚合计算的表达式:
SELECT RN10, RN10 / 10, COUNT(*) FROM
(
SELECT RN, RN/10 AS RN10, RN/100 AS RN100 FROM
(
SELECT RN = -1 + ROW_NUMBER() OVER (ORDER BY 1/0)
FROM master..spt_values
) A
) B
GROUP BY GROUPING SETS ((RN10), (RN10 / 10), ())
ORDER BY 1, 2
它的计划在这里:第一个查询计划
和
SELECT RN10, SUBSTRING(RN,3,99), COUNT(*) FROM
(
SELECT RN, SUBSTRING(RN,2,99) AS RN10 FROM
(
SELECT RN = CAST(-1 + ROW_NUMBER() OVER (ORDER BY 1/0) AS VARCHAR(99))
FROM master..spt_values
) A
) B
GROUP BY GROUPING SETS ((RN10), (SUBSTRING(RN,3,99)), ())
ORDER BY 1, 2
对应的计划在这里:第二个查询计划
这两个查询首先计算一些聚合表达式,RN10 / 10
在第一种情况和SUBSTRING(RN,3,99)
第二种情况下,然后在SELECT
子句中使用相同的表达式,但正如第一个计划所示,它在第一个查询中重新计算,而不是在第二个查询中。
结果,我们NULL
在第一个结果集中有 s,这是非常出乎意料的:
有人可以解释为什么第一个查询进行两次计算(一次在聚合中,一次在 final 中select
),而第二次只计算一次?
我将使用一个更简单的示例,可以清楚地看到预期结果是什么。
查询 1
查询 1 结果
查询 2
查询 2 结果
尽管在 SQL Server 中首先排序,但具有 as 的行排
ORDER BY SurnameInitial
在最后。NULL
SurnameInitial
NULL
查询 1 和 2应该返回相同的结果。问题是 SQL Server 决定将其视为以下 SQL
这对我来说就像一个错误(跟踪标志 8605 表明损坏已经在初始查询树表示中完成)。错误报告。
查询 3
查询 3 个结果
Query3 不符合对列和引用该列的表达式进行分组的问题模式。无论如何,这里甚至不可能发生相同的问题,因为分组集部分相当于
这不会传递
FirstName
上游的整个列(甚至没有保证可以传递的唯一 列FirstName
),因此不可能在此基础上计算表达式。LEFT(FirstName,1)
出于同样的原因,您看不到
(RN10), (SUBSTRING(RN,3,99))
.@i-one在评论中的理由是很可能
无需显式添加计算表达式,如下所示
或者另一个例子是
在这种情况下,这
LEFT(Surname,2)
是允许的,并且计算它的唯一方法是以对该LEFT(Surname,1)
案例有问题的方式进行。