0

我正在使用 MS Project Server 编写报告,但遇到了问题。我需要总结子父层次结构中的一些字段。总和是叶子中值的总和。我写了一个查询,但它只适用于小数据集。

Task - 10
  Task - 2
  Task - 6
    Task - 6
  Task - 2

WITH children AS (
SELECT 
tt.ID, 
CASE '1' WHEN ISNULL(ttt.Id, '1') THEN tt.Value ELSE 0 END as Value,
CASE '1' WHEN ISNULL(ttt.Id, '1') THEN tt.Value2 ELSE 0 END as Value2,
tt.parentid
    FROM [MonitoringExampleDatabase].[dbo].[Table_1] tt
    LEFT JOIN [MonitoringExampleDatabase].[dbo].[Table_1] ttt 
    ON tt.ID = ttt.ParentId

UNION ALL

SELECT t.id, children.value, children.Value2, t.parentid
    FROM children 
    JOIN [MonitoringExampleDatabase].[dbo].[Table_1] t ON children.parentid = t.id
)

SELECT  id, sum(value) as Value, SUM(value2) as Value2
    FROM children 
    GROUP BY id

任何如何优化该查询的想法,现在的问题是递归限制。

4

2 回答 2

1

是否以错误的方式加入第一个 SELECT 的孩子?如果我运行您的代码,我只会得到未汇总的数据:

id          Value       Value2
----------- ----------- -----------
1           10          0
2           2           0
3           6           0
4           6           0
5           2           0

虽然这可能是由于我设置表格的方式,如下所示:

CREATE TABLE [dbo].[Tasks](
[Id] [int] NULL,
[ParentId] [int] NULL,
[Value] [int] NULL,
[Value2] [int] NULL
) ON [PRIMARY]

如果我像这样重构第一个 SELECT 子项,我会得到我认为的预期结果:

WITH children AS (
    SELECT 
      c.ID, 
      c.Value,
      c.Value2,
      c.parentid
    FROM Tasks c
      LEFT JOIN Tasks p
        ON c.ParentId = p.Id

UNION ALL

    SELECT t.id, children.value, children.Value2, t.parentid
        FROM children 
        INNER JOIN Tasks t ON children.parentid = t.id
)

SELECT  id, sum(value) as Value, SUM(value2) as Value2
    FROM children 
    GROUP BY id

结果:

id          Value       Value2
----------- ----------- -----------
1           26          0
2           2           0
3           12          0
4           6           0
5           2           0

关于性能,一般来说,如果您有很多级别,递归算法会很慢。为了获得更好的速度,您可以重构为迭代版本,只要您知道最大可能的级别数。

迭代代码不像递归代码那样漂亮或简洁,但可能更容易理解(因此维护)。

于 2013-04-12T11:23:34.103 回答
0

您可以OPTION (MAXRECURSION 0)在 select 语句的末尾使用来禁用递归限制。

WITH children AS 
(
...
)
SELECT  id, sum(value) as Value, SUM(value2) as Value2
FROM children 
GROUP BY id
OPTION (MAXRECURSION 0)

http://msdn.microsoft.com/en-us/library/ms175972.aspx

于 2013-04-12T08:41:53.177 回答