3

我的查询是:

select A.* 
  from (select r.role_id, 
               r.role_name, 
               r.active, 
               decode( r.entity_type_id, 1000, m.name, 3000, cour.name, 4000, 'Ensenda' ) companyName,
               LISTAGG(p.permission_id, ' | ') WITHIN GROUP (ORDER BY r.role_id) permission_id, 
               LISTAGG(p.permission_name, ' | ') WITHIN GROUP (ORDER BY r.role_id) permission_name, 
               row_number() over (order by r.created_ts desc) as RN, 
               count(*) over () as TOTAL_ROWS, 
               r.created_ts roleCreated 
          from t_role r
          left join t_role_permission rp ON r.role_id = rp.role_id
          left join t_permission p ON rp.permission_id = p.permission_id
          left join merchant m on r.entity_id = m.merchantkey 
          left join courier cour on r.entity_id = cour.courierkey 
         where 1=1
         --and p.permission_id =301446
         group by r.role_id, r.role_name, r.active, r.created_ts,
               decode( r.entity_type_id, 1000, m.name, 3000, cour.name, 4000, 'Ensenda' ) 
      ) A 
where RN between 1 and 100 order by roleCreated desc

我的结果是:

在此处输入图像描述

现在我想以permission_id这样一种方式过滤列表,我想要在permission_id 列中与该permission_id 匹配的所有记录的列表。

例如:假设我为permission_id= 301446. 我想要以下结果

在此处输入图像描述

PS:p.permission_id=301446在 where 子句中添加 and 不会产生预期的结果。

4

3 回答 3

1

对于您要查找的permission_id 值不常见的大型数据集,查询整个数据集然后对聚合结果进行过滤将非常低效,并且看起来像是逻辑上不正确的结果。

您要查找的不是权限 ID 列表包含特定值的角色列表,而是包含特定权限的角色的权限 ID 列表。从逻辑上讲,它最终的结果是一样的,但是更准确地匹配所提出的问题的逻辑实现似乎总是带来可读性和(奇怪的)性能优势。

无论如何,我相信您最好过滤到包含所需权限的角色,然后仅为他们运行查询:

 select A.* 
   from (select r.role_id, 
                r.role_name, 
                r.active, 
                decode( r.entity_type_id, 1000, m.name, 3000, cour.name, 4000, 'Ensenda' ) companyName,
                LISTAGG(p.permission_id, ' | ') WITHIN GROUP (ORDER BY r.role_id) permission_id, 
                LISTAGG(p.permission_name, ' | ') WITHIN GROUP (ORDER BY r.role_id) permission_name, 
                row_number() over (order by r.created_ts desc) as RN, 
                count(*) over () as TOTAL_ROWS, 
                r.created_ts roleCreated 
           from t_role r
           left join t_role_permission rp ON r.role_id = rp.role_id
           left join t_permission p ON rp.permission_id = p.permission_id
           left join merchant m on r.entity_id = m.merchantkey 
           left join courier cour on r.entity_id = cour.courierkey 
          where 1=1
            and r.role_id in (
                select role_id
                from   t_role_permission
                where  permission_id =301446)
          group by r.role_id, r.role_name, r.active, r.created_ts,
                decode( r.entity_type_id, 1000, m.name, 3000, cour.name, 4000, 'Ensenda' ) 
       ) A 
 where RN between 1 and 100 order by roleCreated desc
于 2013-03-06T14:01:30.390 回答
1

基于 PasserBy 评论的答案

select A.* from(select r.role_id, r.role_name, r.active, 
decode( r.entity_type_id, 1000, m.name, 3000, cour.name, 4000, 'Ensenda' ) companyName,
LISTAGG(p.permission_id, ' | ') WITHIN GROUP (ORDER BY r.role_id) permission_id, 
LISTAGG(p.permission_name, ' | ') WITHIN GROUP (ORDER BY r.role_id) permission_name, 
row_number() over (order by r.created_ts desc) as RN, count(*) over () as TOTAL_ROWS, r.created_ts roleCreated 
from t_role r
left join t_role_permission rp ON r.role_id = rp.role_id
left join t_permission p ON rp.permission_id = p.permission_id
left join merchant m on r.entity_id = m.merchantkey 
left join courier cour on r.entity_id = cour.courierkey 
where 1=1

group by r.role_id, r.role_name, r.active, r.created_ts,
decode( r.entity_type_id, 1000, m.name, 3000, cour.name, 4000, 'Ensenda' ) 
)A where RN between 1 and 100 
and REGEXP_LIKE(a.permission_id,'(^|\s)301446(\s|$)')
order by roleCreated desc;
于 2012-12-07T11:06:54.047 回答
0

作为regexp_like路由的替代方案,您可以使用分析查询来实现此目的,特别是 的分析版本listagg(),并使用dense_rank()来生成您的限制“行号”值:

select distinct role_id, role_name, active, companyName, permission_id,
    permission_name, rn, total_rows, roleCreated
from (
    select *
    from (
        select r.role_id, 
            r.role_name, 
            r.active, 
            decode(r.entity_type_id, 1000, m.name, 3000, cour.name,
                4000, 'Ensenda') companyName,
            p.permission_id as raw_permission_id,
            listagg(p.permission_id, ' | ')
                within group (order by p.permission_id)
                    over (partition by r.role_id) permission_id, 
            listagg(p.permission_name, ' | ')
                within group (order by p.permission_id)
                    over (partition by r.role_id) permission_name, 
            dense_rank() over (order by r.created_ts desc) as rn,
            count(distinct r.role_id) over () as total_rows, 
            r.created_ts roleCreated
        from t_role r
        left join t_role_permission rp ON r.role_id = rp.role_id
        left join t_permission p ON rp.permission_id = p.permission_id
        left join merchant m on r.entity_id = m.merchantkey 
        left join courier cour on r.entity_id = cour.courierkey 
    )
    where raw_permission_id = 301446
)
where rn between 1 and 100
order by roleCreated desc;

如果您自己运行内部查询,您将看到每个role_id;的多个结果。每个都有listagg组件,但也将包括(临时)各个permission_id值,我将其别名为raw_permission_id.

然后,下一个查询可以过滤您感兴趣的确切权限对于单个权限,正如您在此处所拥有的,这将最多为每个角色提供一行,但如果您正在寻找一系列中的一个权限,那么您可能会得到重复(如果一个角色匹配多个)。因此,外部查询排除raw_permission_id和添加distinct以抑制任何重复。

于 2013-03-06T13:10:16.197 回答