2

为简单起见,假设我有以下表格:

role

id  name        inherits
----------------------------------
1   Base        null
2   Role2       1
3   Role3       1
4   Role3Child  3

item

id  name            org_id      
----------------------------------
1   item1            4210
2   item2            4210
3   item3            4210
4   item4            4210
5   item5            4210
6   item6            4210


role_item_junction

id  role_id     item_id      item_value
----------------------------------
1   1       1            true
2   1       2            false
3   2       3            D
4   3       3            F
5   4       4            12

这里的 role_id 4 继承了从 role_id 1 继承的 role_id 3 继承了所有项目。

当我查询与 role_id 4 相关的所有项目时,我想返回:

  1. 分配给 role_id 4 和 item_value 的所有项目
  2. role_id 4 继承的所有项目及其 item_values
  3. 某个 org_id 中的所有其他项目

如何编写一个查询来返回 role_id 4 应该有权访问的所有项目?当我查询 role_id 4 时,我希望输出类似于以下内容:

id(item.id) org_id      name(item.name)     item_value
------------------------------------------------------------------
1       4210        item1           true
2       4210        item2           false
3       4210        item3           F
4       4210        item4           12
5       4210        item5           NULL <--not in the junction table
6       4210        item6           NULL <--not in the junction table

不知道如何从我的左连接返回连接表中继承的项目值:

@orgid varchar(5) = '4210',
@roleid int = 4


SELECT item.*, ri.item_value AS selected_item_value
--SNIP LOTS OF OTHER COLUMNS RETURNED

FROM item
LEFT JOIN role_item AS ri ON item.id = ri.item_id 
AND ri.role_id = @roleid
???? how do I return the ri.item_value of items that roleid 4 inherits from?
--SNIP LOTS OF OTHER IRRELEVANT JOINS

WHERE 
((@orgid IS NULL or @orgid = '') or item.org_id = @orgid) AND
item.date_archived IS NULL 
AND ri.date_archived IS NULL
4

1 回答 1

1

如果没有递归 CTE,我想不出一种简单的方法来解决它,但这应该可行:

;WITH roleCascaded AS
(SELECT id, id as inherits
FROM role
UNION ALL
SELECT r2.id, r1.inherits
FROM role r1 
INNER JOIN roleCascaded r2 on r1.id = r2.inherits AND r1.inherits IS NOT NULL
)
SELECT item.*, ri.item_value AS selected_item_value
FROM item
LEFT OUTER JOIN role_item AS ri ON item.id = ri.item_id 
LEFT OUTER JOIN roleCascaded AS rc ON rc.inherits = ri.role_id AND rc.id = @roleid
WHERE 
((@orgid IS NULL or @orgid = '') or item.org_id = @orgid) AND
item.date_archived IS NULL 
AND ri.date_archived IS NULL
于 2012-09-21T23:10:51.050 回答