2012-12-07 26 views
3

假設有一個下面的表table1,說明親子關係和公制是:SUM指標的歸一化邏輯層次

Parent | Child | Metric (of a child) 
------------------------------------ 
name0 | name1 | a 
name0 | name2 | b 
name1 | name3 | c 
name2 | name4 | d 
name2 | name5 | e 
name3 | name6 | f 

特點:
1)兒童總是有且只有1個父母;
2)父母可以有多個孩子(name2具有name4和name5作爲孩子);
3)這個「層次結構」中的層次數和任何給定父項的子項數是任意的,並且不相互依賴;

我需要SQL請求,將返回結果集,每個名字和它的所有後代的度量的總和下降到底層加上本身,因此在本例表中的結果將是(在NAME1仔細看):

Name | Metric 
------------------ 
name1 | a + c + f 
name2 | b + d + e 
name3 | c + f 
name4 | d 
name5 | e 
name6 | f 

(NAME0是無關緊要的,並且可以被排除)。

它應該是ANSI或Teradata SQL。

我得到儘可能可以返回給定名稱的所有後代的SUM(公制)遞歸查詢:

WITH RECURSIVE temp_table (Child, metric) AS 
( 
    SELECT root.Child, root.metric 
    FROM table1 root 
    WHERE root.Child = 'name1' 
    UNION ALL 
    SELECT indirect.Child, indirect.metric 
    FROM temp_table direct, table1 indirect 
    WHERE direct.Child = indirect.Parent 
) 
SELECT SUM(metric) FROM temp_table; 

有沒有辦法把這個查詢成需要的名字作爲函數一個參數並返回這個總和,所以可以這樣調用它?

SELECT Sum_Of_Descendants (Child) FROM Table1; 

有關如何從不同的角度來處理這個任何建議,將不勝感激爲好,因爲即使上面的方法是可實現的,這將是業績不佳 - 會有很多的閱讀指標的迭代(在這個例子中值f將被讀取3次)。理想情況下,查詢應該只讀取一次每個名稱的度量。

+1

您是否考慮過遞歸視圖定義,在查詢它時指定了子項? –

+0

@RobPaller:我認爲這是一個好主意;發佈它作爲答案,以便我可以投票! – BellevueBob

+0

這將如何比遞歸查詢優勢?我仍然必須在視圖定義中硬編碼最初的「根」名稱,對吧? – Alex

回答

1

編輯:此答案適用於支持Common Table表達式的SQL Server 2005及更高版本。當我第一次回答問題時,我沒有注意到teradata標籤。希望這個答案仍然相關,因爲語法看起來幾乎是一樣的。

這可以在SQL Server通過擴大每個級別的層次結構

with recursive temp_table (RootValue, Child, Metric) 
as 
(select 
    root.Child, root.Child, root.Metric 
from table1 root 
union all 
select 
    direct.RootValue, indirect.Child, indirect.Metric 
from temp_table direct join table1 indirect on indirect.Parent = direct.Child 
) 
select 
    RootValue, SUM(Metric) 
from temp_table 
group by RootValue; 

的(公共表表達式)CTE的定義有除了兒童和公制一個RootValue柱來實現。 CTE遞歸地將給定的RootValue的兒童&度量值關聯起來。

鑑於此CTE,期望的輸出只是聚合在RootValue列上的問題。

+0

謝謝。花了我一些時間來弄清楚它是如何工作的 - 我看到的所有例子都有硬編碼的初始值,所以我認爲這是遞歸的必要條件。校長在這裏解釋得很好 - http://www.postgresql.org/docs/current/static/queries-with.html – Alex