我的数据库模式中有两个表,表示与自身具有多对多关系的实体。
Role
---------------------
+RoleID
+Name
RoleHasChildRole
---------------------
+ParentRoleID
+ChildRoleID
基本上,我需要能够编写一个查询:
给定一组角色,递归返回所有相关角色的唯一集合。
这是一个MSSQL 2008数据库。
修改
需要一些样本数据。所以这里:
RoleID Name
------------------------------------
1 'Admin'
2 'SuperUser'
3 'Lackey'
4 'Editor'
5 'CanEditSomething'
6 'CanDeleteSomething'
7 'CanCreateSomething'
8 'CanViewSomething'
ParentRoleID ChileRoleID
------------------------------------
1 5
1 6
1 7
1 8
2 4
4 5
4 8
因此,Admin角色的查询将返回:
'管理'
'CanEditSomething'
'CanDeleteSomething'
'CanCreateSomething'
'CanViewSomething'
SuperUser的查询将返回:
'超级用户'
“编辑器”
'CanViewSomething'
'CanEditSomething'
答案 0 :(得分:3)
非常常见的CTE用法:
WITH RecursiveRole AS (
SELECT RoleID AS RecursiveRoleID
FROM Role
WHERE Name = @parameter
UNION ALL
SELECT ChildRoleID AS RecursiveRoleID
FROM RoleHasChildRole
INNER JOIN RecursiveRole
ON RoleHasChildRole.ParentRoleID = RecursiveRole.RecursiveRoleID
)
SELECT RoleID, RoleName
FROM RecursiveRole
INNER JOIN Role
ON RecursiveRoleID = RoleID
这只是 down 角色树。我留下了一个作为练习上升的东西。
编辑看起来你只想沿着树走下去。这个查询做得很好。
返回测试数据的以下结果:
SET @parameter = 'Admin'
1 Admin
5 CanEditSomething
6 CanDeleteSomething
7 CanCreateSomething
8 CanViewSomething
SET @parameter = 'SuperUser'
2 SuperUser
4 Editor
5 CanEditSomething
8 CanViewSomething
答案 1 :(得分:0)
我的QCD(快速,廉价和肮脏)示例:
假设组织中有一个简单的员工经理关系。我们将有一个EmployeeManager表,EmpMan,它有2列EmpID和ManID。为简单起见,我将省略其他细节(索引,具有员工姓名/联系人的辅助表等)
CREATE TABLE [dbo].[EmpMan]( [EmpID] [int] NOT NULL, [ManID] [int] NOT NULL) GO;
insert into dbo.EmpMan select 2,1
union select 3,1
union select 4,1
union select 31,3
union select 32,2
union select 43,4 `/* 3X report to 3 and 4X report to 4*/`
union select 310,31
union select 314,31 `/* 31X reports to 31*/`
union select 56,5 union select 87,8 `/*empID 56 reports to 5 and 87 reports to 8, 5 and 8 do not have managers*/`
CTE查询可以执行递归查询:
with Manager AS (
/*initialization query*/
select EmpID,ManID from EmpMan where ManID=1/* assuming that your VP ID is 1, or it can be the top most person whom you want to query on*/
union all
/*recursive query*/
select E.EmpID,E.ManID from EmpMan E
join Manager M on E.ManID=M.EmpID)
select * from Manager