Hao*_*est 11 t-sql common-table-expression
我编写了一个非常简单的CTE表达式,它检索用户所属的所有组的列表.
规则是这样的,用户可以在多个组中,并且组可以嵌套,以便组可以是另一个组的成员,此外,组可以是另一个组的共同成员,因此组A是组的成员B组和B组也是A组的成员.
我的CTE是这样的,显然它会产生无限递归:
;WITH GetMembershipInfo(entityId) AS( -- entity can be a user or group
SELECT k.ID as entityId FROM entities k WHERE k.id = @userId
UNION ALL
SELECT k.id FROM entities k
JOIN Xrelationships kc on kc.entityId = k.entityId
JOIN GetMembershipInfo m on m.entityId = kc.ChildID
)
Run Code Online (Sandbox Code Playgroud)
我找不到一个简单的解决方案来回溯我已记录的那些组.
我在考虑在CTE中使用额外的varchar参数来记录我访问过的所有组的列表,但是使用varchar太粗糙了,不是吗?
有没有更好的办法?
Joh*_*wey 25
您需要在递归中累积一个标记字符串.在下面的例子中,我有一个从A,B,C,D到A的循环关系,我避免使用sentinel字符串的循环:
DECLARE @MyTable TABLE(Parent CHAR(1), Child CHAR(1));
INSERT @MyTable VALUES('A', 'B');
INSERT @MyTable VALUES('B', 'C');
INSERT @MyTable VALUES('C', 'D');
INSERT @MyTable VALUES('D', 'A');
; WITH CTE (Parent, Child, Sentinel) AS (
SELECT Parent, Child, Sentinel = CAST(Parent AS VARCHAR(MAX))
FROM @MyTable
WHERE Parent = 'A'
UNION ALL
SELECT CTE.Child, t.Child, Sentinel + '|' + CTE.Child
FROM CTE
JOIN @MyTable t ON t.Parent = CTE.Child
WHERE CHARINDEX(CTE.Child,Sentinel)=0
)
SELECT * FROM CTE;
Run Code Online (Sandbox Code Playgroud)
结果:
Parent Child Sentinel
------ ----- --------
A B A
B C A|B
C D A|B|C
D A A|B|C|D
Run Code Online (Sandbox Code Playgroud)