2012-03-21 36 views
2

我有3個表:在T-SQL中這是否可能是令人討厭的遞歸?

Region 
(
    Region_id int, 
    Parent_id int, 
    Region_name varchar(50) 
) 

RegionStore 
(
    Region_id int, 
    Store_id int 
) 

StoreItems 
(
    Store_id int, 
    Item_id int 
) 

區表是在區域遞歸可以有父區,如果父母id爲null這是一個頂級的區域。地區可能達到4級。

我需要爲每個區域的每個區域獲得物品計數。如果一個地區是父母 - 我需要爲所有的孩子計數儘可能多的級別和分支。換句話說,如果區域255具有父項130,並且130具有父項67,並且67具有父項2,則需要對2(包括所有子項和分支)進行計數,並且對包括其所有子項和分支的計數爲67,等等。我需要在一次通話中爲所有地區獲取此信息。這可能使用遞歸查詢嗎?

+0

是 - http://msdn.microsoft.com/en-us/library/ ms186243(v = sql.90).aspx – Yuck 2012-03-21 18:23:14

+0

@Yuck - 是的我可以得到父子關係顯示得很好(我實際使用表變量代替CTE),但它得到的項目計數,我卡住。我可以讓他們達到最底層的水平 - 但這是我所能得到的。 – 2012-03-21 18:25:43

回答

3

試試這個:

DECLARE @Region TABLE 
( 
    Region_id int, 
    Parent_id int, 
    Region_name varchar(50) 
) 

DECLARE @RegionStore TABLE 
( 
    Region_id int, 
    Store_id int 
) 

DECLARE @StoreItems TABLE 
( 
    Store_id int, 
    Item_id int 
) 

INSERT @Region 
SELECT 2, NULL, '2' UNION ALL 
SELECT 67, 2, '67' UNION ALL 
SELECT 130, 67, '130' UNION ALL 
SELECT 255, 130, '255' UNION ALL 
SELECT 1, NULL, '1' UNION ALL 
SELECT 68, 2, '68' 

-- add more test data here 

;WITH CTE AS (
    SELECT 
     Region_id, 
     Parent_id, 
     Region_name, 
     Region_id AS Region_id_calc 
    FROM @Region 

    UNION ALL 

    SELECT 
     r.Region_id, 
     r.Parent_id, 
     r.Region_name, 
     CTE.Region_id_calc AS Region_id_calc 
    FROM CTE 
    INNER JOIN @Region AS r 
     ON r.Region_id = CTE.Parent_id 
) 
SELECT 
    CTE.Region_id, 
    Region_name, 
    COUNT(DISTINCT Item_Id) 
FROM CTE 
INNER JOIN @RegionStore AS s 
    ON CTE.Region_id_calc = s.Region_id 
INNER JOIN @StoreItems AS i 
    ON s.Store_id = i.Store_id 
GROUP BY 
    CTE.Region_id, 
    Region_name 
ORDER BY 
    CTE.Region_id 
+0

+80正確使用CTE所有的無限遞歸的榮耀。 – 2012-03-21 19:27:25

+0

我認爲這可能工作,如果我改變一件事,並從item_id的計數中刪除DISTINCT,因爲我想要計算所有項目不僅僅是所有類型的項目。我會讓你知道和感謝。 – 2012-03-21 19:33:41

+0

謝謝,祝你好運! – 2012-03-21 19:35:54

1

要做到這一點的一種方法是在遞歸查詢的初始部分包含額外的列。這允許您在遞歸開始的地方「傳遞」。在下面的例子中,額外的列記住了Root_id和Root_name。這應該列出所有地區,其總項目計數:

; with Regions as 
     (
     select Region_id as Root_id 
     ,  Region_name as Root_name 
     ,  * 
     from @Region 
     union all 
     select p.Root_id 
     ,  p.Root_name 
     ,  c.* 
     from Regions p 
     join @Region c 
     on  p.Region_id = c.Parent_id 
     ) 
select r.Root_name 
,  count(distinct si.Item_id) as ItemCount 
from Regions r 
left join 
     @RegionStore rs 
on  rs.Region_id = r.Region_id 
left join 
     @StoreItems si 
on  si.Store_id = rs.Store_id 
group by 
     r.Root_name 

Working example on SE Data.

+0

看起來你需要將SUM更改爲COUNT – 2012-03-21 19:06:53

+0

@AndreyGurinov:謝謝,這是無可爭議的正確,編輯:) – Andomar 2012-03-21 19:10:41

+0

這也適用,但該網站只會讓我標記一個作爲答案 - uv - 謝謝 – 2012-03-21 19:50:06