0

我有一个目录元数据。其中一些列是用户 ID、内容 ID、角色。角色列是';' 分隔值。例如, 在此处输入图像描述

在上表中,结果列指示该行是否应出现在查询中。

管理员角色:管理员、实施者、设置最终用户角色:最终用户 1、最终用户 2、最终用户 3 等。(这些是假名,实际名称不同,这里不能透露)。

为了进一步扩展,标准是,查询应该产生至少具有一个非管理员最终用户角色的行。有五个管理员类型的角色和大量的非管理员最终用户角色。行可以有尽可能多的角色。

以下是我正在考虑的方法: 1. 创建一个包含所有角色的临时表,并在 where 条件下查询角色的表,并使用 INSTR 找出最终用户角色。我不想这样做,因为我试图在我的查询中避免使用 pl/sql。2.正则表达式

我一直在尝试使用正则表达式,但没有得到任何结果。

注意:请不要建议更改数据布局,因为我无法控制它!

更新:好的,这是我正在考虑的另一种方法。- 从列字符串中删除所有与管理员相关的角色。- 检查列表的长度。选择非零长度。我猜这将需要 5 个替换函数,一个用于每个管理员类型角色,一个用于计算长度(本质上是计算分号数 +1)。我正在尝试这个。如果可行,我将更新我的答案。否则邀请更多建议!

4

3 回答 3

0

这是一个可怕的、可怕的数据布局。让我假设你无法改变它。有时我们会被其他人非常非常糟糕的设计决定所困扰。

让我还假设用户的层次结构只有一层。如果是这样,您可以使用单个join

select c.*,
       (case when ';' || c.roles || ';' like '%;Admin;%' then 'Yes'
             when ';' || cu.roles || ';' like '%;Admin;%' then 'Yes'
             else 'No'
        end) as Outcome
from content c left join
     content cu
     on ';' || c.roles|| ';' like '%;End User ' || cu.id || ';%';

编辑:

如果您有多个管理员角色,只需使用正则表达式:

select c.*,
       (case when regexp_like(';' || c.roles || ';', ';Admin;|;Implementor;|;Setup;') then 'Yes'
             when regexp_like(';' || cu.roles || ';', ';Admin;|;Implementor;|;Setup;') then 'Yes'
             else 'No'
        end) as Outcome
from content c left join
     content cu
     on ';' || c.roles|| ';' like '%;End User ' || cu.id || ';%';
于 2017-06-21T21:03:16.533 回答
0

好的,我尝试了最新的方法(有问题的更新),它有点工作。我实现了 3 个管理员角色。不得不为此使用长字符串操作。但是,如果列出了 3 个连续的管理员角色(管理员;设置;实施者;最终用户 1),这将不起作用,因为我将有 3 个“;” . 有人可以提出一种更好的方法来用一个分号替换多个分号吗?

另请建议是否可以对这种方法进行任何改进。

with new_roles as 
(select id,
 roles,
trim(both ';' from (replace(
    replace(
        replace(
            replace(roles,'Setup',''), 
            'Administrator', ''),
        'Implementor', ''),
    ';;', ';'))) as role_new
 from my_table)

select id, roles, role_new
from new_roles
where (LENGTH(role_new) - LENGTH(REPLACE(role_new,';','')))+1 is not NULL;
于 2017-06-21T21:54:11.040 回答
0

更新:我在这里发布我的最终解决方案,以防它可能对其他人有用:

with new_roles as 
(select id,
 roles,
trim(both ';' from (
    regexp_replace(
    regexp_replace(roles, '(Setup)|(Administrator)|(Implementor)','')),
    ';{1;}',';'))) as role_new
 from my_table)

select id, roles, role_new
from new_roles
where (LENGTH(role_new) - LENGTH(REPLACE(role_new,';','')))+1 is not NULL;
于 2017-07-03T15:25:10.077 回答