2016-09-27 162 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