2013-04-12 111 views
0

我正在使用MS Project Server編寫報表,但遇到了問題。我需要在子父級層次結構中總結一些字段。總和是樹葉中的值的總和。我寫了一個查詢,但它只適用於一小部分數據。SQL優化子父查詢

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 

任何想法如何優化該查詢,現在的問題是遞歸的限制。

+1

請指定存儲在MonitoringExampleDatabase表中的幾個示例行。 – Devart

+0

是的,如果你可以提供一些樣本數據和你的預期結果,你會得到更快的幫助。 –

回答

0

您可以在選擇語句的末尾使用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

+0

我試過'OPTION(MAXRECURSION 0)',但是當我殺了它時查詢需要2分鐘。該查詢有一些錯誤,會導致循環。 有沒有更好的方法來達到這個目標。 –

+0

說實話,我沒有真正抓住時間仔細檢查你的代碼。我現在來看看它 - 但是你的CTE的第一部分 - UNION應該只返回頂層行之前,最下面的部分將它們連接到他們的孩子。 –

1

是在第一個SELECT周圍走錯了路的孩子們一起的?如果我運行代碼,我剛剛回來unsummed數據:

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

我認爲這應該可以正常工作。一個小小的評論 - 第一部分的左連接是不必要的。您沒有從任務p中選擇任何內容。 –

+0

好點 - 我專注於重構 – Ackroydd