我有一张内容元数据表。一些列是用户ID,内容ID,角色。角色列是';'分开的值。例如,
在上表中,“结果”列指示该行是否应出现在查询中。
管理员角色:管理员,执行者,设置 最终用户角色:最终用户1,最终用户2,最终用户3等。 (这些是虚拟名称,实际名称有所不同,这里不能透露)。
要进一步扩展,标准是,查询应该产生具有至少一个非管理员最终用户角色的行。有五个管理员类型角色和大量非管理员最终用户角色。行可以拥有尽可能多的角色。
以下是我正在考虑的方法: 1.创建包含所有角色的临时表,并在角色的条件中查询表,并使用INSTR查找最终用户角色。我不想这样做,因为我试图在我的查询中避免使用pl / sql。 2. Regexp
我一直在试用regexp,但没有随处可见。
注意:请不要建议更改数据布局,因为我无法控制它!
更新: 好的,这是我想的另一种方法。 - 从列字符串中删除所有与管理员相关的角色。 - 检查列表的长度。选择非零长度。 我猜这将需要5个替换函数,一个用于每个管理类型角色,另一个用于计算长度(这将基本上计算分号+1)。 我正在尝试这个。如果有效,我会更新我的答案。否则邀请更多建议!
答案 0 :(得分: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 || ';%';
答案 1 :(得分: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;
答案 2 :(得分: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;