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_value
  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 に答える