これは、再帰CTEを使用したソリューションです。 lvl
を使用しました level
以降の列ヘッダーとして Oracleの予約語です。用語には他の違いもあります。すぐ上のレベルには「親」を使用し、> =0ステップには「祖先」を使用します(ノードをそれ自体の祖先として表示するという要件に対応するため)。 ORDER BY
を使用しました 出力を自分のものと一致させる句。順序付けられた行が必要な場合と不要な場合があります。
あなたの質問は、再帰CTEの代わりに階層クエリを使用してこれを実行できるかどうかを確認するために、階層クエリについてもう一度詳しく読むように促しました。実際、CONNECT_BY_PATH
を使用することで、できることはすでにわかっています。 、ただしsubstr
を使用 その上で、階層パスのトップレベルを取得するだけでは、まったく満足のいくものではありません。より良い方法が必要です。 (それが階層クエリでそれを行う唯一の方法である場合、それが利用可能であれば、私は間違いなく再帰CTEルートに行きます)。適切なソリューションが見つかった場合は、ここに階層クエリソリューションを追加します。
with h ( node, parent ) as (
select 1 , null from dual union all
select 2 , 1 from dual union all
select 3 , 2 from dual
),
r ( node , ancestor, steps ) as (
select node , node , 0
from h
union all
select r.node, h.parent, steps + 1
from h join r
on h.node = r.ancestor
)
select node, ancestor,
1+ (max(steps) over (partition by node)) as lvl, steps
from r
where ancestor is not null
order by lvl, steps desc;
NODE ANCESTOR LVL STEPS
---------- ---------- ---------- ----------
1 1 1 0
2 1 2 1
2 2 2 0
3 1 3 2
3 2 3 1
3 3 3 0
追加 :階層クエリソリューション
OK-見つけた。両方のソリューションをテストして、どちらが優れているかを確認してください。異なる設定でのテストから、再帰CTEは階層クエリよりもかなり高速でしたが、それは特定の状況に依存する可能性があります。また、再帰CTEはOracle11.2以降でのみ機能します。階層型ソリューションは古いバージョンで機能します。
Anatoliyのものと一致するようにもう少しテストデータを追加しました。
with h ( node, parent ) as (
select 1 , null from dual union all
select 2 , 1 from dual union all
select 3 , 2 from dual union all
select 4 , 2 from dual union all
select 5 , 4 from dual
)
select node,
connect_by_root node as ancestor,
max(level) over (partition by node) as lvl,
level - 1 as steps
from h
connect by parent = prior node
order by node, ancestor;
NODE ANCESTOR LVL STEPS
---------- ---------- ---------- ----------
1 1 1 0
2 1 2 1
2 2 2 0
3 1 3 2
3 2 3 1
3 3 3 0
4 1 3 2
4 2 3 1
4 4 3 0
5 1 4 3
5 2 4 2
5 4 4 1
5 5 4 0