SQL优化子父查询

时间:2013-04-12 08:21:42

标签: sql sql-server sql-server-2008

我正在使用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

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

2 个答案:

答案 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)

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