递归查询帮助

时间:2010-03-29 16:11:40

标签: sql sql-server sql-server-2008 recursion

我的数据库模式中有两个表,表示与自身具有多对多关系的实体。

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'

2 个答案:

答案 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