我们有一个角色继承结构,而不是最高级别的过滤,它假定默认情况下每个人都获得最低级别的角色,图形描述如下:
role.Everyone //lowest level; everyone gets this role
role.Applications // everyone assigned this role gets applications && everyone roles
role.Databases // everyone assigned this role gets databases && applications && everyone roles
role.SoftwareSubscriber
role.Client_All // etc.
role.Client
role.ITClient
role.Client
role.NewsService // everyone assigned this role gets NewsService && Client && Everyone
// && Client_All roles, since Client is also a child of Client_All
role.ClientDeliverable // etc.
role.Employee
role.Corporate
role.Marketing
role...
...
我会检索所有“父母”(真的,孩子,但无论如何)和他们任何给定角色的递归父母。例如,我希望查询要求role.Databases
的父母返回role.Applications
和role.Everyone
。同样,我希望一个查询要求role.NewsService
的父母返回role.Client
,role.Everyone
和role.Client_All
,因为role.Client
是role.Everyone
和role.Client_All
。
我试图在MSDN's CTE example之后按如下方式对查询进行建模,但是我无法获得所有递归父项。任何人都可以在正确的方向上引导我的CTE查询吗?
CREATE TABLE #ATTRIBASSIGN
(
ATTRIBID int not null
, ITEMID int not null
, ITEMCLASS VARCHAR(10) NOT NULL DEFAULT ('ATTRIB')
, CONSTRAINT PK_ATTRIBASSIGN_ATTRIBID_ITEMID_ITEMCLASS PRIMARY KEY (ATTRIBID, ITEMID, ITEMCLASS)
)
CREATE TABLE #ATTRIBPROP
(
ATTRIBID int not null identity(1,1) primary key
, ATTRIBNAME VARCHAR(50) not null
)
GO
INSERT INTO #ATTRIBPROP (ATTRIBNAME)
VALUES ('role.Databases'), ('role.Applications'), ('role.Everyone'), ('role.Client_All'), ('role.Employee'), ('role.SoftwareSubscriber'),
('role.Client'), ('role.ITClient'), ('role.NewsService'), ('role.ClientDeliverable'), ('role.Corporate'), ('role.Marketing')
GO
INSERT INTO #ATTRIBASSIGN (ATTRIBID, ITEMID)
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Everyone'
AND B.ATTRIBNAME = 'role.Applications'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Everyone'
AND B.ATTRIBNAME = 'role.Client_All'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Everyone'
AND B.ATTRIBNAME = 'role.Client'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Everyone'
AND B.ATTRIBNAME = 'role.Employee'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Applications'
AND B.ATTRIBNAME = 'role.Databases'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Applications'
AND B.ATTRIBNAME = 'role.SoftwareSubscriber'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Client_All'
AND B.ATTRIBNAME = 'role.Client'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Client_All'
AND B.ATTRIBNAME = 'role.ITClient'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Client'
AND B.ATTRIBNAME = 'role.NewsService'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Client'
AND B.ATTRIBNAME = 'role.ClientDeliverable'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Employee'
AND B.ATTRIBNAME = 'role.Corporate'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Employee'
AND B.ATTRIBNAME = 'role.Marketing'
GO
WITH RoleStructure (parentRole, currentRole, Level)
AS
(
SELECT B.ITEMID, B.ATTRIBID, 0 level
FROM #ATTRIBASSIGN B
WHERE B.ATTRIBID NOT IN
(
SELECT ITEMID
FROM #ATTRIBASSIGN C
WHERE B.ATTRIBID = C.ITEMID
)
AND B.ITEMCLASS = 'attrib'
UNION ALL
SELECT B.ITEMID, B.ATTRIBID, D.level - 1
FROM #ATTRIBASSIGN B
INNER JOIN RoleStructure D ON B.ATTRIBID = D.parentRole
WHERE B.ITEMCLASS = 'attrib'
)
SELECT B.ATTRIBNAME, C.ATTRIBNAME, level
FROM RoleStructure A
INNER JOIN #ATTRIBPROP B ON A.parentRole = B.ATTRIBID
INNER JOIN #ATTRIBPROP C ON A.currentRole = C.ATTRIBID
答案 0 :(得分:4)
感谢全面的SQL和示例数据 - 这使得构建答案变得更加容易!看起来你的主要错误是让自己在父母与父母之间感到困惑。儿童。我认为你过分关注结构是如何“反向”并且颠覆你的想法。我对您的SQL进行了两次主要编辑,以使其正常工作。
1)翻转父母&目前的项目。在“AttribAssign”中,我将ATTRIBID视为“父”,将“ITEMID”视为“子”,因此您有一个很好的常规树。我也最终在UNION的下半部分(递归部分)翻转来排队
2)我没有过滤'锚'数据集。额外的10行是必要的,以保持递归像你想要的那样。我这样做是因为你想为任何父/子组合提供一行输出,而不管递归的级别如何。您的原始表格具有所有“直接”组合。您希望扩展每个“直接”以包含N + 1级别的间接。您的查询提供的只是“直接”关系。通过保留所有原始链接,我们可以构建该集合以更好地查找所有链接,而不管间接级别如何。令人困惑,是的,但它确实有效。
;WITH RoleStructure (parentRole, currentRole, Level)
AS
(
SELECT B.ATTRIBID, B.ITEMID, 0 level
FROM #ATTRIBASSIGN B
WHERE B.ITEMCLASS = 'attrib'
UNION ALL
SELECT D.parentRole, B.ITEMID, D.level - 1
FROM #ATTRIBASSIGN B
INNER JOIN RoleStructure D ON B.ATTRIBID = D.currentRole
WHERE B.ITEMCLASS = 'attrib'
)
SELECT a.parentRole, a.currentRole, B.ATTRIBNAME, C.ATTRIBNAME, level
FROM RoleStructure A
INNER JOIN #ATTRIBPROP B ON A.parentRole = B.ATTRIBID
INNER JOIN #ATTRIBPROP C ON A.currentRole = C.ATTRIBID