CTE - 反向层次结构

时间:2011-01-04 15:34:20

标签: tsql sql-server-2005

我需要像特定联系人的群组路径一样生成面包屑。

T_GROUP存储实际的组层次结构:

GROUP_ID    NAME            PARENT_ID   LEVEL
    7      g1              NULL         1
    80    Workgroups      7            2
    82    Advocacy        80           3

T_CONTACT_GROUP表存储属于联系人的组:

CONTACT_ID  GROUP_ID 
55          82
56            7
55            7

现在,我想将结果集设置为以下联系人ID 55 :请注意,g1在预期结果集中已经两次,因为联系人55也已分配了组7。

contactId GROUP_ID NAME PARENT_ID   LEVEL
55        7     g1      NULL        1
55        80       g1|Workgroups 7 2
55       82        g1|Workgroups|Advocacy 80 3
55       7         g1 NULL 1

1 个答案:

答案 0 :(得分:2)

至少有两种方法可以做到这一点。 你在标题中提到了CTE,所以我先用它来做。 从链接here我有一个hiererchical CTE的例子,一个小按摩,它将代表父母而不是孩子:

WITH Hierarchy (Group_ID, Name, Parent_ID, Level) AS
(
    SELECT Group_ID, Name, Parent_ID, Level
    FROM T_Group
    WHERE Contact_id = @Leaf
UNION ALL 
    SELECT g.Group_ID, g.Name, g.Parent_ID, g.Level
    FROM T_Group g
    INNER JOIN Hierarchy h ON g.Group_ID = h.Parent
)

这个CTE将放在一个存储过程或表User Defined Function中,取一个@Leaf参数(你看的叶节点。在你的例子中它是82然后是7)。

这个问题是分层CTE可能非常昂贵,特别是如果在更深的树结构上工作或重复调用。缓存可以提供帮助,但还有其他选择。

另一种方法是将父级的层次结构存储在字符串连接字段旁边:

GROUP_ID NAME      PARENT_ID LEVEL PARENTS
82        Advocacy 80        3     |7|80|82|

然后您可以执行以下操作:

SELECT p.Group_ID, g.Name, g.Parent_ID, g.Level
FROM T_GROUP g
CROSS JOIN dbo.StringSplit('|', Parents) p
WHERE p.Value = g.Group_ID

获取父母的所有详细信息。这往往比使用CTE处理查找更有效。这意味着当您将新记录插入GROUP时,您也必须构建父字段。通常要处理此问题,您将创建一个存储过程,为您创建组,根据需要构建父级。