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:and p.permission_id=301446in where句を追加しても、望ましい結果は得られません。

4

3 に答える 3

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 に答える
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 に答える
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です。

次のクエリアウトでは、関心のある正確な権限でフィルタリングできます。ここにあるように、単一の権限の場合、役割ごとに最大1行が与えられますが、次の範囲の1つを探している場合は権限があると、重複する可能性があります(役割が複数で一致した場合)。したがって、外部クエリはとを除外しraw_permission_idて追加distinctし、重複を抑制します。

于 2013-03-06T13:10:16.197 に答える