1

背景

我有一个表、用户表和一个group_members表。

groups { group_ varchar(50) not null, etc... }
users  { user_id varchar(50) not null, etc... }
group_members { group_ varchar(50 not null, member varchar(50) not null }

我的要求表明一个组可以有其他组作为成员。用户需要被视为他们所属的任何组的所有组的成员。
例如,考虑这些表中的以下数据:

group_members              | groups         | users    |
========================== | ============== | ======== |
group_          member     | group_         | user_id  |
-------------------------- | -------------- | -------- |
'SYSTEM_ADMIN'  'OE_ADMIN' | 'SYSTEM_ADMIN' | 'USER    |
'SYSTEM_ADMIN'  'AR_ADMIN' | 'OE_ADMIN'     |          |
'SYSTEM_ADMIN'  'USER'     | 'AR_ADMIN'     |          |

问我想要的结果是 什么组是“用户”的成员?应该

member
==============
'SYSTEM_ADMIN'
'OE_ADMIN'
'AR_ADMIN'

问题

我已经构建了以下查询并为我提供了所需的结果,但它看起来有点复杂。

WITH GM
AS (
    SELECT GROUP_, MEMBER FROM group_members 
       WHERE member IN (SELECT group_ FROM groups)
)
SELECT group_ FROM group_members WHERE member = 'USER'
UNION
SELECT MEMBER AS GROUP_ FROM GM 
   WHERE group_ in (SELECT group_ FROM group_members WHERE member = 'USER')

有关如何使此查询更简单或更简洁的任何建议?

4

2 回答 2

0

您的递归 CTE 看起来不错。

它的表现如何?

我不认为有任何重要的方法可以让它变得更简单——递归 CTE 总是看起来有点乱。

WHERE IN 等价于 JOIN,但我不认为它更具可读性,并且执行计划应该非常等价。

您的根行可以表示为递归行之前的 CTE,但它不会真正节省太多可读性:

WITH root AS ()
     ,CTE AS ()
SELECT FROM ROOT 
    UNION
SELECT FROM CTE

在任何情况下,您都可以将它放在视图或内联表值函数(带有参数)中,以便在系统的其他地方轻松使用它,这样您就不必经常看到它。

我为层次结构所做的事情是构建一个更高性能的扁平化/非规范化版本,并在触发器或计时器上对其进行更新,并将其用作只读性能增强器。例如,在技术支持系统中,我们构建一个问题可以在层次结构中标记一个问题时,我们填写了所有父母(打印机 - > HP-> LaserJet)时,在选择一个孩子时,可以轻松查询问题任何版本的 Windows 上的 hp 打印机或 Windows XP 上的laserjets 问题。

于 2012-06-15T21:02:36.687 回答
0

根据@Cade Roux 的回答,进一步的思考将我引导至以下存储过程

ALTER PROCEDURE GetUserGroups
@user_id varchar(50)
AS
BEGIN
SET NOCOUNT ON;

SELECT group_ FROM group_members WHERE member = @user_id
UNION
SELECT MEMBER AS GROUP_ FROM group_members
WHERE group_ IN (SELECT group_ FROM group_members WHERE member = @user_id) 
      AND member != @user_id
END

这简化了原始查询,并正确地满足了我的要求,即获取 @user_id 所属的组名列表以及顶级组成员的组名。

此代码仅允许组中的组达到一个级别。

于 2012-06-18T16:45:13.410 回答