如何在Oracle DB

时间:2017-07-06 17:20:28

标签: sql oracle

我有一个用户可以访问软件应用程序的表。用户可以具有多个访问,其具有由字母数字id表示的应用程序的不同方面。类似地,多个用户可以具有相同或不同的访问集。 例如。

Table ACCESSTAB
USER             |       USERACCESS                  
-----------------------------------------
Cust1            |       BA1
Cust1            |       BB2
Cust2            |       BA1
Cust2            |       BB2
Cust3            |       CB1
Cust3            |       BA1

我想根据同一组访问对客户进行分组。例如:

USER             |       GROUP                  
-----------------------------------------
Cust1            |       Group1
Cust2            |       Group1
Cust3            |       Group2

目前,我为此目的为一些重要用户创建了表格,如下所示:

Table USERGROUP
GROUP             |       ACCESS                  
-----------------------------------------
Group1            |       BA1
Group1            |       BB2
Group2            |       CB1
Group2            |       BA1

以下查询比较两个表。

select a.USER,u.GROUP from ACCESSTAB a, USERGROUP u where not exists
(select USERACCESS from ACCESSTAB where USER=a.USER order by 1
MINUS
select ACCESS from USERGROUP where GROUP=u.GROUP order by 1)

我想在不使用USERGROUP表的情况下对用户进行分组,因为很难为所有用户维护,更不用说添加访问需要手动配置。表现并不重要。

欢迎任何建议/协助。提前致谢。

4 个答案:

答案 0 :(得分:1)

同意@ jeff6times7您应该重新考虑您的数据模型以使访问权限受到群组驱动,但与此同时......您可以使用listagg()生成每个用户的访问权限列表:

select username, listagg(useraccess, ',') within group (order by useraccess) as groupaccess
from accesstab
group by username;

USERNAME GROUPACCESS         
-------- --------------------
Cust1    BA1,BB2             
Cust2    BA1,BB2             
Cust3    BA1,CB1             

并从不同的聚合中生成组:

select 'Group' || rownum as groupname, groupaccess
from (
  select distinct listagg(useraccess, ',') within group (order by useraccess) as groupaccess
  from accesstab
  group by username
  order by groupaccess
);

GROUPNAME GROUPACCESS         
--------- --------------------
Group1    BA1,BB2             
Group2    BA1,CB1             

他们将他们加在一起,例如有两个CTE:

with user_cte (username, groupaccess) as (
  select username, listagg(useraccess, ',') within group (order by useraccess)
  from accesstab
  group by username
),
group_cte (groupname, groupaccess) as (
  select 'Group' || rownum, groupaccess
  from (
    select distinct listagg(useraccess, ',') within group (order by useraccess) as groupaccess
    from accesstab
    group by username
    order by groupaccess
  )
)
select u.username, g.groupname
from user_cte u
join group_cte g on g.groupaccess = u.groupaccess
order by u.username;

USERNAME GROUPNAME
-------- ---------
Cust1    Group1   
Cust2    Group1   
Cust3    Group2   

或者您可以使用第一个CTE构建第二个CTE,这样您只能点击实际表格一次:

with user_cte (username, groupaccess) as (
  select username, listagg(useraccess, ',') within group (order by useraccess)
  from accesstab
  group by username
),
group_cte (groupname, groupaccess) as (
  select distinct 'Group' || dense_rank () over (order by groupaccess), groupaccess
  from user_cte
)
select u.username, g.groupname
from user_cte u
join group_cte g on g.groupaccess = u.groupaccess
order by u.username;

USERNAME GROUPNAME
-------- ---------
Cust1    Group1   
Cust2    Group1   
Cust3    Group2   

甚至没有第二次CTE:

with user_cte (username, groupaccess) as (
  select username, listagg(useraccess, ',') within group (order by useraccess)
  from accesstab
  group by username
)
select distinct username,
  'Group' || dense_rank() over (order by groupaccess) as groupname
from user_cte;

USERNAME GROUPNAME
-------- ---------
Cust1    Group1   
Cust2    Group1   
Cust3    Group2   

(......这几乎是xQbert的方法)

如果它有用,您还可以在输出中包含汇总的groupaccess,以列出每个组中的权限,但这似乎并不是必需的。

当然,只要用不同的访问组合添加(或更新)用户,就会生成(或删除!)组,并且现有组的编号可能会发生变化 - 这可能会造成混淆,但是不是你的问题。如果这是一个问题,那么你就会坚持维护你的中间表。

答案 1 :(得分:1)

只是一个简单的例子:

with AccessTab as 
(SELECT '1' muser ,'BA1' useraccess from dual UNION ALL
SELECT '1','BB2' from dual UNION ALL
SELECT '2','BA1' from dual UNION ALL
SELECT '2','BB2' from dual UNION ALL
SELECT '3','CB1' from dual UNION ALL
SELECT '3','BA1' from dual),
cte as (SELECT muser, listagg(userAccess,',') within group (order by useraccess) GRP From AccessTab group by muser)
SELECT A.muser, dense_Rank() over ( order by a.GRP) as mGroup  
FROM cte a

结果:

Muser    mGroup
2        1
1        1
3        2

答案 2 :(得分:0)

看起来你的关系是:

  1. 用户拥有一项或多项权限
  2. 用户属于一个或多个群组
  3. 一个群组拥有一项或多项权限
  4. 当您说“难以为所有用户维护”时,您的意思并不十分清楚,但看起来您可能会说出一组用户权限(#1)和一组权限(#3)必须是平等的,你担心让它们保持一致是很困难的。如果我的假设是正确的,那么我建议你删除规则#1,删除ACCESSTAB表,并将USERGROUP表重命名为GROUP_ACCESS。这将消除更新异常。

答案 3 :(得分:0)

这可以通过LISTAGG()函数完成。

SELECT USER, LISTAGG(USERACCESS, ', ') WITHIN GROUP (ORDER BY USER) AS USER_ACCESS_GROUP
FROM ACCESSTAB
GROUP BY USER

结果将是

USERNAME| USER_ACCESS_GROUP
Cust1     BA1, BB2             
Cust2     BA1, BB2             
Cust3     BA1, CB1

如果每个组都有一个特殊名称,则可以将LISTAGG()包装在DECODE()函数中。