我正在使用一张goups表。
GroupMembers(GroupName,MemberName)
每个组成员都有一行,一个组可以包含其他组和用户。
我想提取一个GroupName,MemberName对的列表,其中MemberName只是一个用户列表。基本上,扁平化树。我之前做过类似的事情并手动编写查询,将每个级别的叶子导出到一个单独的表中,然后在达到最后一级后合并这个。
树似乎不平衡,并且没有任何固定数量的级别。我一直在寻找递归查询的例子,并且没有太多运气来实现它们。
有没有人有任何好的指示我可以去哪里为这个提供优雅的解决方案?
非常感谢!
ps如果有帮助,我正在使用SQL Server 2008。
更新:我偶然发现了递归CTE。我唯一的问题是数据中存在循环引用:(。
这是我用于查询的代码: -
WITH Members AS
(
--Init
SELECT GroupName, MemberName
FROM GroupMembers
WHERE MemberName NOT IN (Select GroupName from GroupMembers)
UNION ALL
--Recursive Exe
SELECT h.GroupName, h.MemberName
FROM GroupMembers h INNER JOIN Members m
ON h.MemberName = m.GroupName
)
Select * into GroupMembersFlattened from Members OPTION (MAXRECURSION 1500)
有没有办法在执行上述查询之前排除循环引用/清除数据?
谢谢!
循环/循环参考示例 循环引用的一个示例是数据包含以下内容: -
GroupMember, MemberName
Group1, Group2
Group1, User1
Group2, Group3
Group2, User2
Group3, Group1
感谢小费Mikael!
答案 0 :(得分:1)
这是排除周期的方法
WITH Members AS
(
--Anchor
SELECT
GroupName,
MemberName,
0 As isCycle,
'.' + CAST(MemberName As varchar(max)) + '.' As [path]
FROM GroupMembers
WHERE
MemberName NOT IN (Select GroupName from GroupMembers)
UNION ALL
--Recursive call
SELECT
h.GroupName,
h.MemberName,
CASE WHEN m.[path] like '%.' + CAST(h.MemberName as varchar(max)) + '.%' THEN 1 ELSE 0 END As isCycle,
m.[path] + CAST(h.MemberName as varchar(max)) + '.' As [path]
FROM GroupMembers h
JOIN Members m
ON h.MemberName = m.GroupName
WHERE
m.isCycle = 0
)
SELECT
*
FROM
Members
WHERE
Members.isCycle = 0
答案 1 :(得分:0)
我想提取一份清单 GroupName,MemberName对在哪里 MemberName只是一个用户列表。
我可能不明白你的结构,但对我而言,你似乎只需要这样做。
SELECT GroupName, MemberName
FROM GroupMembers
WHERE MemberName NOT IN (Select GroupName from GroupMembers)
这将为您提供所有叶节点。如果一个组可以是一个叶子,或者如果用户可以拥有成员,则需要其他东西来区分用户和组。
您的样本数据的结果:
GroupName MemberName
--------- ----------
Group1 User1
Group2 User2