あなたのr
エイリアスとrights
それが参照するテーブルは、作成しているインラインビューの範囲内にありません。階層を生成する必要がありますが、これはインラインビューで引き続き実行でき、それをrights
に結合します。 folderid
を介したテーブル 。
階層は次の場所から取得できます:
select connect_by_root(folderid) as rootid, folderid,
sys_connect_by_path(folderid, '/') as path
from folders
connect by parentfolderid = prior folderid
order by rootid, path;
ROOTID FOLDERID PATH
---------- ---------- ------------------------------
5162 5162 /5162
5162 28568 /5162/28568
5162 6343 /5162/6343
5534 5534 /5534
5534 41578 /5534/41578
5534 113867 /5534/41578/113867
5534 127030 /5534/41578/127030
5534 5162 /5534/5162
5534 28568 /5534/5162/28568
5534 6343 /5534/5162/6343
5534 5538 /5534/5538
5538 5538 /5538
...
これはほとんどあなたがやっていたことですが、これは任意の開始点からすべての子孫を見つけ、開始点をrootid
としてキャプチャします。 。 (私はpath
を投入しました 階層を視覚化するだけでも不十分です。結果ではそれを望まないようです。
次に、それを権利テーブルに結合できます。ここで、各ユーザーのfolderid
すべてのrootid
に一致します 。重複が一覧表示されるため(たとえば、685は直接または5534経由で5538に到達できます)、distinct
を使用できます。 それらを排除するには:
select distinct r.userid, f.folderid
from rights r
join (
select connect_by_root(folderid) as rootid, folderid
from folders
connect by prior folderid = parentfolderid
) f
on f.rootid = r.folderid
order by r.userid, f.folderid;
データとの組み合わせで16の異なる組み合わせが得られます:
USERID FOLDERID
---------- ----------
685 5162
685 5534
685 5538
685 6343
685 28568
685 41578
685 113867
685 127030
686 5162
686 6343
686 28568
686 41578
686 113867
686 127030
725 113867
725 127030
再帰的サブクエリファクタリング を使用することもできます。 階層クエリの代わりに:
with rcte (userid, folderid) as (
select r.userid, f.folderid
from rights r
join folders f on f.folderid = r.folderid
union all
select rcte.userid, f.folderid
from rcte
join folders f on f.parentfolderid = rcte.folderid
)
select distinct userid, folderid
from rcte
order by userid, folderid;
アンカーメンバーは、トップレベルの権限を取得するための2つのテーブル間の単純な結合です。次に、再帰メンバーは、既に見つかった子のアクセス許可を探します。同じ結果、わずかに異なるアプローチ。