2014-05-22 74 views
1

我想解決一個遞歸SQL問題,本質上是聚合一組記錄的狀態。遞歸SQL,SQL服務器2012

出於問題的目的 - 有兩個表格。一個維護聚合/層次結構「GROUP_MEMBERS」,另一個包含單個項目「ITEMS」。

「GROUP_MEMBERS」 看起來類似於(ID爲GROUPID,CHILDTYPE爲一組,1爲單獨的項目是0,和ID是子項ID(因此GROUPID爲0型,商品ID爲類型1)

ID | CHILDTYPE | CHILDID 

1  0  2 
1  1  1 
2  1  2 
2  1  3 
2  1  4 

在這個例子中,我的「項目」表將只有兩列:

ID | STATUS 

1  0 
2  1 
3  0 
4  0 
5  0 

有效什麼,我試圖做的是拉了回來所有「項目」,ID和狀態,一組遞歸下(因爲組可以包含其他組)。因此,對於我提供的示例數據,如果我通過了GROUPI D爲1,它會返回ITEMS 1-4的狀態; GROUPID 2將是ITEMS 2-4與他們的狀態,等等。

我假設我需要通過函數來​​做這件事,並返回一個表,但我甚至不知道從哪裏開始。

+0

您是否需要每個組的ITEMS(如表值函數)或所有組的ITEMS的總列表? – martennis

+0

另外,你是否只有1級遞歸,或者更多? – martennis

+0

可能有超過1級的遞歸 - 我更願意爲每個組的ITEMS獲得一個TVF,我認爲。我想對返回的狀態執行一些數學運算。 – user1695263

回答

3

這是一個很好的謎題,得告訴你:) 希望它是你想要它做的。

DECLARE @GroupRootID INT = 1 
DECLARE @GROUP_MEMBERS TABLE (ID int, CHILDTYPE int, CHILDID int) 
DECLARE @ITEMS TABLE (ID int, STATUS int) 

INSERT INTO @GROUP_MEMBERS VALUES 
(1,0,2), (1,1,1), (2,1,2), (2,0,3), (2,0,4), (2,1,3), (2,1,4), (3,1,5), (4,1,5) 

INSERT INTO @ITEMS VALUES 
(1,0), (2,1), (3,0), (4,0), (5,1) 

--    1 
--   / \ 
--   2  items   items: 1 => 1,1,1 
--  /| \ 
--  3 4 items   items: 2,3,4 => 2,1,2 - 2,1,3 - 2,1,4 
--  | \ 
-- items items    items (3): 5 => 3,1,5 
--        items (4); 5 => 4,1,5 

/* Recursivly build the GROUP tree (groups that have subgroups, CHILDTYPE=0), but NOT the lead nodes (CHILDTYPE = 1) */ 
;WITH GROUP_TREE 
AS 
(
    /* SELECT all parents */ 
    SELECT ParentGroups.*, 0 AS LEVEL 
    FROM @GROUP_MEMBERS AS ParentGroups 
    WHERE ParentGroups.CHILDTYPE = 0 
    AND ParentGroups.ID = @GroupRootID 

    UNION ALL 

    /* SELECT all childs groups for the parents */ 
    SELECT ChildGroups.*, LEVEL + 1 
    FROM @GROUP_MEMBERS AS ChildGroups 
    INNER JOIN GROUP_TREE AS Parent ON Parent.CHILDID = ChildGroups.ID 
    WHERE ChildGroups.CHILDTYPE = 0 
) 

/* We now have all groups with their subgroups (not leaf nodes) */ 
/* Then join the leaf nodes (groups that are no subtree) */ 
/* Finally union the items from the root node and join the ITEMS to the leaf nodes to get the status */ 
/* Mind you though that ITEM 5 is linked double and will be returned NON-distinct */ 

SELECT ITEMS.* 
FROM (
    SELECT GROUPS.* 
    FROM @GROUP_MEMBERS AS GROUPS 
    INNER JOIN GROUP_TREE ON GROUP_TREE.CHILDID = GROUPS.ID 
    WHERE GROUPS.CHILDTYPE = 1 

    UNION ALL 

    SELECT GROUPS.* 
    FROM @GROUP_MEMBERS AS GROUPS 
    WHERE GROUPS.CHILDTYPE = 1 
    AND GROUPS.ID = @GroupRootID 
) AS GROUP_ITEMS 
INNER JOIN @ITEMS AS ITEMS ON GROUP_ITEMS.CHILDID = ITEMS.ID 
+0

+1是我在一段時間內看到的最好解釋的答案之一。 –