2010-03-29 148 views
1

我在我的數據庫模式中有兩個表,表示一個實體與自己具有多對多關係。遞歸查詢幫助

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 

所以對於管理員角色的查詢將返回:

'管理員'
'CanEditSomething'
'CanDeleteSomething'
'CanCreateSomething'
'CanViewSomething'

並且超級用戶的查詢將返回:

'超級用戶'
'編輯'
'CanViewSomething'
'CanEditSomething'

+1

我們看一些樣本數據,或者你有什麼到目前爲止已經試過...... – 2010-03-29 16:16:29

+0

我不知道添加的樣本數據將提供什麼好處。這個結構非常明顯。至於遞歸查詢,我已經看過CTE的例子,但它們似乎都處理一個自引用的表。 – Josh 2010-03-29 16:20:56

+0

樣本數據將顯示我們是否在您的結構中存在一個圈... – 2010-03-29 16:28:08

回答

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 

這一個唯一無二角色樹。我留下了一個作爲練習的練習題。


編輯看起來你只是想反正走下來的樹。這個查詢做得很好。

返回在您的測試數據結果如下:

SET @parameter = 'Admin' 
1 Admin 
5 CanEditSomething 
6 CanDeleteSomething 
7 CanCreateSomething 
8 CanViewSomething 

SET @parameter = 'SuperUser' 
2 SuperUser 
4 Editor 
5 CanEditSomething 
8 CanViewSomething 
+0

太棒了!沒有意識到CTE太簡單了。正如你所看到的,我對他們的經驗很少:( – Josh 2010-03-29 16:45:13

+0

只是想說這對我有幫助,需要一個自頂向下和自下而上的多對多遞歸查詢。它工作。 – Chris 2015-03-15 22:24:13

0

我的QCD(快速,廉價和骯髒的)例子:

假設在一個簡單的員工管理的關係組織。我們將有一個EmployeeManager表EmpMan,它有兩列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