[英]How can I make a this selection of groups and members simpler and more efficient?
我有一个组表, 用户表和一个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' | |
我想要的问题询问结果是“ USER”的成员属于哪个组? 应该
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')
关于如何使此查询更简单或更混乱的任何建议?
您的递归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问题。
根据@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所属的组名列表以及作为顶级组成员的组名。
此代码仅允许将组中的组提高到一个级别。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.