2016-09-27 157 views
2

我掙扎着爬一個遞歸CTE爲所需,但仍然沒有機會工作.. 所以,我有以下類似的表結構:SQL遞歸層次結構

tblMapping

map_id | type_id | name | parent_id 
1   1   A1  0 
2   1   A2  0 
3   1   A3  1 
4   1   A4  3 
5   2   B1  0 
6   2   B2  5 
7   2   B3  6 
8   1   A5  4 
9   2   B4  0 

tblRoleGroup

role_group_id | type_id | map_id | desc_id 
1    1   0   null 
1    2   0   null 
2    1   3   1 
2    2   6   0 
3    1   8   1 
3    2   9   1 

在tblRoleGroup中,desc_id字段指:

null - allow all (used only in combination with map_id=0) 
0 - allow all from parent including parent 
1 - allow only current node 

仍然在tblRoleGroup如果map_id=0那麼查詢應該得到相同的TYPE_ID所有元素

查詢結果應該是這樣的:

role_group_id | type_id | map_id | path 
1    1   1   A1 
1    1   2   A2 
1    1   3   A1.A3 
1    1   4   A1.A3.A4 
1    1   8   A1.A3.A4.A5 
1    2   5   B1 
1    2   6   B1.B2 
1    2   7   B1.B2.B3 
1    2   9   B4 
2    1   3   A1.A3 
2    2   6   B1.B2 
2    2   7   B1.B2.B3 
3    1   8   A1.A3.A4.A5 
3    2   9   B4 

查詢下面僅僅解決的一個組成部分預期的結果,但我無法使其工作作爲預期的結果..

WITH Hierarchy(map_id, type_id, name, Path) AS 
    (
    SELECT t.map_id, t.type_id, t.name, CAST(t.name AS varchar(MAX)) AS Expr1 
     FROM dbo.tblMapping AS t 
      LEFT JOIN dbo.tblMapping AS t1 ON t1.map_id = t.parent_id 
     WHERE (t1.parent_id=0) 
    UNION ALL 
    SELECT t.map_id, t.type_id, t.name, CAST(h.Path + '.' + t.name AS varchar(MAX)) AS Expr1 
     FROM Hierarchy AS h 
      JOIN dbo.tblMapping AS t ON t.parent_id = h.map_id 
    ) 
SELECT h.map_id, h.type_id, t.role_group_id, h.Path AS Path 
    FROM Hierarchy AS h 
    LEFT JOIN dbo.tblRoleGroup t ON t.map_id = h.map_id  

有人可以幫助我嗎? 謝謝

+0

所以當'desc_id = 0'時,你希望整個鏈(父母,自己和孩子)成爲公司luded?例如。 'role_group_id = 2 type_id = 2 map_id = 6 and output = B1.B2'?但爲什麼包含'B1.B2.B3'的行呢? – NickyvV

+0

實際上,輸出應該與預期表中的完全一樣,這意味着應該有兩行輸出B1.B2和B1.B2.B3,因爲查詢還應該包括來自map_id = 6 – rosuandreimihai

+0

cte代碼問題的所有子代你已經提出:''Hierarchy'的列數少於列表中指定的數量.',它不能編譯我正在寫的測試代碼 – Tanner

回答

1

起初,我創建帶來通過map_id的所有後代的功能:

CREATE FUNCTION mapping (@map_id int) 
RETURNS TABLE 
AS 
RETURN 
( 
    WITH rec AS (
    SELECT map_id, 
      [type_id], 
      CAST(name as nvarchar(max)) as name, 
      parent_id 
    FROM tblMapping 
    WHERE map_id = @map_id 
    UNION ALL 
    SELECT m.map_id, 
      m.[type_id], 
      r.name+'.'+m.name, 
      m.parent_id 
    FROM rec r 
    INNER JOIN tblMapping m 
    ON m.parent_id = r.map_id 
    ) 

    SELECT * 
    FROM rec 
); 
GO 

然後運行這個命令:

;WITH rec AS (
SELECT map_id, 
     [type_id], 
     CAST(name as nvarchar(max)) as name, 
     parent_id 
FROM tblMapping 
WHERE parent_id=0 
UNION ALL 
SELECT m.map_id, 
     m.[type_id], 
     r.name+'.'+m.name, 
     m.parent_id 
FROM rec r 
INNER JOIN tblMapping m 
ON m.parent_id = r.map_id 
) 


SELECT t.role_group_id, 
     r.[type_id], 
     r.map_id, 
     r.name as [path] 
FROM tblRoleGroup t 
CROSS JOIN rec r 
WHERE r.[type_id] = CASE WHEN t.desc_id IS NULL AND t.map_id = 0 THEN t.[type_id] ELSE NULL END 
    OR r.map_id = CASE WHEN t.desc_id = 1 THEN t.map_id ELSE NULL END 
    OR r.map_id IN (
        SELECT map_id 
        FROM dbo.mapping (CASE WHEN t.desc_id = 0 THEN t.map_id ELSE NULL END) 
        ) 
ORDER BY role_group_id, r.[type_id], r.map_id 

會給你:

role_group_id type_id map_id path 
1    1  1  A1 
1    1  2  A2 
1    1  3  A1.A3 
1    1  4  A1.A3.A4 
1    1  8  A1.A3.A4.A5 
1    2  5  B1 
1    2  6  B1.B2 
1    2  7  B1.B2.B3 
1    2  9  B4 
2    1  3  A1.A3 
2    2  6  B1.B2 
2    2  7  B1.B2.B3 
3    1  8  A1.A3.A4.A5 
3    2  9  B4 
+0

謝謝,它的工作! – rosuandreimihai

+0

我的榮幸! :) – gofr1