0

在 SQL Server 2019 中,分析函数不会返回我在递归公用表表达式上下文中所期望的结果。考虑以下非递归 T-SQL 查询:

WITH SourceData (RowNum, Uniform, RowVal) AS (
  SELECT 1, 'A', 'A' UNION ALL
  SELECT 2, 'A', 'B' UNION ALL
  SELECT 3, 'A', 'C' UNION ALL
  SELECT 4, 'A', 'D'
),
RecursiveCte0 (RowNum, Uniform, RowVal, MinVal, SomeSum, RowNumCalc, RecursiveLevel) AS (
  SELECT RowNum, Uniform, RowVal, RowVal, RowNum, CAST(RowNum AS BIGINT), 0
  FROM SourceData
),
RecursiveCte1 (RowNum, Uniform, RowVal, MinVal, SomeSum, RowNumCalc, RecursiveLevel) AS (
  SELECT * FROM RecursiveCte0
  UNION ALL
  SELECT
    RowNum, Uniform, RowVal,
    MIN(MinVal) OVER (PARTITION BY Uniform),
    SUM(RowNum) OVER (PARTITION BY Uniform),
    ROW_NUMBER() OVER (PARTITION BY Uniform ORDER BY RowNum),
    RecursiveLevel + 1
  FROM RecursiveCte0
)
SELECT *
FROM RecursiveCte1
ORDER BY RecursiveLevel, RowNum;

结果:

RowNum Uniform RowVal MinVal SomeSum RowNumCalc RecursiveLevel
1      A       A      A      1       1          0
2      A       B      B      2       2          0
3      A       C      C      3       3          0
4      A       D      D      4       4          0
1      A       A      A      10      1          1
2      A       B      A      10      2          1
3      A       C      A      10      3          1
4      A       D      A      10      4          1

正如预期的那样MINSUM、 和ROW_NUMBER函数会根据 中的所有行生成适当的值RecursiveCte0。我希望以下递归查询在逻辑上与上面的非递归版本相同,但它会产生不同的结果:

WITH SourceData (RowNum, Uniform, RowVal) AS (
  SELECT 1, 'A', 'A' UNION ALL
  SELECT 2, 'A', 'B' UNION ALL
  SELECT 3, 'A', 'C' UNION ALL
  SELECT 4, 'A', 'D'
),
RecursiveCte (RowNum, Uniform, RowVal, MinVal, SomeSum, RowNumCalc, RecursiveLevel) AS (
  SELECT RowNum, Uniform, RowVal, RowVal, RowNum, CAST(RowNum AS BIGINT), 0
  FROM SourceData
  UNION ALL
  SELECT
    RowNum, Uniform, RowVal,
    MIN(MinVal) OVER (PARTITION BY Uniform),
    SUM(RowNum) OVER (PARTITION BY Uniform),
    ROW_NUMBER() OVER (PARTITION BY Uniform ORDER BY RowNum),
    RecursiveLevel + 1
  FROM RecursiveCte
  WHERE RecursiveLevel < 1
)
SELECT *
FROM RecursiveCte
ORDER BY RecursiveLevel, RowNum;

结果:

RowNum Uniform RowVal MinVal SomeSum RowNumCalc RecursiveLevel
1      A       A      A      1       1          0
2      A       B      B      2       2          0
3      A       C      C      3       3          0
4      A       D      D      4       4          0
1      A       A      A      1       1          1
2      A       B      B      2       1          1
3      A       C      C      3       1          1
4      A       D      D      4       1          1

对于三个分析函数中的每一个,似乎只在每个单独行的上下文中应用分组,而不是在该级别的所有行中应用。如果我对(SELECT NULL). 根据MSDN,我希望分析函数适用于整个递归级别:

CTE 递归部分中的分析和聚合函数应用于当前递归级别的集合,而不是应用于 CTE 的集合。像这样的函数ROW_NUMBER只对当前递归级别传递给它们的数据子集进行操作,而不是对传递给 CTE 递归部分的整个数据集进行操作。

为什么这两个查询会产生不同的结果?有没有办法通过递归公用表表达式有效地使用分析函数?

4

0 回答 0