简而言之,我试图计算其父母拥有的树根的百分比,进一步向上。如何仅在 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 子句执行此操作的尝试之一是:
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: 模型维度中的非唯一寻址
由于类似的原因,使用UNIQUE SINGLE REFERENCE失败,即 ORDER BY 子句不是唯一的。
tl;博士
有没有一种简单的方法可以仅使用 SQL 来计算其父母所拥有的树根的百分比?如果我在 MODEL 的正确轨道上,我哪里错了?
1. 我还想避免 PL/SQL SQL 上下文切换。我意识到这是很短的时间,但如果不每天增加几分钟,这将很难快速完成。