我正在使用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
任何想法如何优化该查询,现在问题是递归的限制。
答案 0 :(得分:1)
第一个孩子选择中的连接是错误的吗?如果我运行你的代码,我只是将数据恢复为未编号:
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]
如果我像这样重构第一个儿童选择,我得到的结果是我想要的结果:
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
关于性能,一般来说,如果你有很多级别,递归算法会很慢。为了获得更好的速度,您可以重构为迭代版本,只要您知道最大可能的级别数。
迭代代码不像递归那样漂亮或简洁,但可能更容易理解(因此维护)。
答案 1 :(得分:0)
您可以在select语句的末尾使用OPTION (MAXRECURSION 0)
来禁用递归限制。
WITH children AS
(
...
)
SELECT id, sum(value) as Value, SUM(value2) as Value2
FROM children
GROUP BY id
OPTION (MAXRECURSION 0)