【问题标题】:Return inherited values from join on junction table?从连接表上的连接返回继承的值?
【发布时间】:2012-09-20 20:50:22
【问题描述】:

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

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 3 继承了所有的项目,而role_id 3 继承自role_id 1。

当我查询与 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

【问题讨论】:

  • 顺便说一句,我尝试创建一个 CTE 并设置每个角色的继承级别,然后声明一个计数器并循环直到达到该级别,但似乎必须有更好的方法。

标签: sql sql-server inheritance join common-table-expression


【解决方案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

【讨论】:

  • 感谢您的回答。这与我在您回答之前的想法相同。但是,角色继承的想法给原本极其简单的应用程序增加了不必要的复杂性,因此我将其逐步淘汰。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-26
  • 1970-01-01
  • 2011-07-22
  • 1970-01-01
  • 1970-01-01
  • 2014-09-01
  • 1970-01-01
相关资源
最近更新 更多