簡単に言えば、ツリーのさらに上の親が所有するツリーのルートのパーセンテージを計算しようとしています。SQL だけでこれを行うにはどうすればよいですか?
これが私の(サンプル)スキーマです。階層自体は非常に単純ですが、追加の があることに注意してくださいholding_id
。これは、単一の親が子のさまざまな部分を「所有」できることを意味します。
create table hierarchy_test (
id number -- "root" ID
, parent_id number -- Parent of ID
, holding_id number -- The ID can be split into multiple parts
, percent_owned number (3, 2)
, primary key (id, parent_id, holding_id)
);
そしていくつかのサンプルデータ:
insert all
into hierarchy_test values (1, 2, 1, 1)
into hierarchy_test values (2, 3, 1, 0.25)
into hierarchy_test values (2, 4, 1, 0.25)
into hierarchy_test values (2, 5, 1, 0.1)
into hierarchy_test values (2, 4, 2, 0.4)
into hierarchy_test values (4, 5, 1, 1)
into hierarchy_test values (5, 6, 1, 0.3)
into hierarchy_test values (5, 7, 1, 0.2)
into hierarchy_test values (5, 8, 1, 0.5)
select * from dual;
次のクエリは、実行したい計算を返します。SYS_CONNECT_BY_PATH の性質上、私の知る限り、計算自体を実行することはできません。
select a.*, level as lvl
, '1' || sys_connect_by_path(percent_owned, ' * ') as calc
from hierarchy_test a
start with id = 1
connect by nocycle prior parent_id = id
この例ではありませんが、データには周期的な関係があります。
現時点では、非常に単純な関数を使用して、列の文字列calc
を数値に変換します
create or replace function some_sum ( P_Sum in varchar2 ) return number is
l_result number;
begin
execute immediate 'select ' || P_Sum || ' from dual'
into l_result;
return l_result;
end;
/
これはばかげた方法のように思われ、動的 SQL 1の解析にかかる追加の時間を避けたいと思います。
理論的には、MODEL 句を使用してこれを計算できるはずです。私の問題は、ツリーの非一意性が原因です。これを行うために MODEL 句を使用する私の試みの1つは次のとおりです。
select *
from ( select a.*, level as lvl
, '1' || sys_connect_by_path(percent_owned, ' * ') as calc
from hierarchy_test a
start with id = 1
connect by nocycle prior parent_id = id
)
model
dimension by (lvl ll, id ii)
measures (percent_owned, parent_id )
rules upsert all (
percent_owned[any, any]
order by ll, ii = percent_owned[cv(ll), cv(ii)] * nvl( percent_owned[cv(ll) - 1, parent_id[cv(ll), cv(ii)]], 1)
)
当然のことながら、これは次の場合に失敗します。
ORA-32638: MODELディメンションのアドレス指定が一意ではありません
UNIQUE SINGLE REFERENCEの使用は、同様の理由で失敗します。つまり、ORDER BY 句が一意ではないということです。
tl;dr
SQL のみを使用して、親が所有するツリーのルートのパーセンテージを計算する簡単な方法はありますか? MODEL で正しい軌道に乗っている場合、どこで間違っているのでしょうか?
1. PL/SQL SQL コンテキスト スイッチも避けたいと思います。これはほんのわずかな時間であることはわかっていますが、1 日に数分追加せずにすばやく行うのは非常に困難です。