简体   繁体   English

如何使这种选择的组和成员更简单,更有效?

[英]How can I make a this selection of groups and members simpler and more efficient?

Background 背景

I've got a group table, users table, and a group_members table. 我有一个表, 用户表和一个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 }

My requirements state that a group can have other groups as members. 我的要求是,一个组可以将其他组作为成员。 The user needs to be considered a member of all groups that any group they are a member of. 必须将用户视为所有用户所属的所有组的成员。
For Example, consider the following data in these tables: 例如,请考虑这些表中的以下数据:

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'     |          |

My desired result of asking the question What groups is 'USER' a member of? 我想要的问题询问结果是“ USER”的成员属于哪个组? should be 应该

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

Question

I've got the following query built and providing me with the required results, but it looks a little complex. 我已经构建了以下查询,并为我提供了所需的结果,但是看起来有点复杂。

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')

Any suggestions on how to make this query simpler, or less cluttered? 关于如何使此查询更简单或更混乱的任何建议?

Your recursive CTE looks fine. 您的递归CTE看起来不错。

How does it perform? 效果如何?

I don't think there's any significant way to make it a lot simpler - the recursive CTEs always look kind of messy. 我认为没有任何有效的方法可以使它更简单-递归CTE总是看起来很凌乱。

The WHERE IN is equivalent to a JOIN, but I don't see it as being more readable and the execution plan should be pretty equivalent. WHERE IN等效于JOIN,但我不认为它更具可读性,并且执行计划应该相当等效。

Your root row could be represented as a CTE before the recursive one, but it won't really save much in readability: 您的根行可以在递归行之前表示为CTE,但实际上并不会节省太多可读性:

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

In any case, you could put this in a view or inline table-valued-function (with a parameter) to make it easy to use from elsewhere in the system so you don't have to see it very much. 无论如何,您都可以将其放在视图或内联表值函数(带有参数)中,以使其易于在系统中的其他位置使用,因此不必太多查看。

Something I've done for hierarchies is to build a more high-performance flattened/denormalized version and update it on a trigger or timer and use that as a read-only performance enhancer. 我为层次结构所做的事情是构建更高性能的扁平化/非规范化版本,并在触发器或计时器上对其进行更新,并将其用作只读性能增强器。 For instance, in a technical support system we build where a question could be tagged in a hierarchy, we filled in all the parents (printers->hp->laserjet) when a child was selected, so it was easy to query for problems with hp printers on any version of Windows or problems with laserjets on Windows XP. 例如,在我们建立的技术支持系统中,可以在一个层次结构中标记问题,当选择一个孩子时,我们填写了所有父母(打印机-> hp-> laserjet),因此很容易查询以下问题任何版本的Windows上的hp打印机,或Windows XP上的Laserjets问题。

Based on @Cade Roux's answer, further reflection guided me to the following Stored Procedure 根据@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

This simplifies the original query, and properly fulfills my requirement to get back a list of group names that @user_id is a member of, as well as the names of the groups that are members of the top-level group. 这简化了原始查询,并正确满足了我的要求,以获取@user_id所属的组名列表以及作为顶级组成员的组名。

This code only allows groups in groups to one level. 此代码仅允许将组中的组提高到一个级别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM