【发布时间】:2026-01-11 23:40:01
【问题描述】:
简而言之,我正在尝试计算其父级拥有的树根的百分比,在树的更上方。如何仅在 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;
/
这似乎是一种荒谬的做法,我宁愿避免花费额外的时间来解析动态 SQL1。
理论上,我认为,我应该可以使用 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 上下文切换。我意识到这是很短的时间,但如果不每天增加几分钟,这将很难快速完成。
【问题讨论】:
-
您是否考虑过使用递归子查询分解而不是连接方式?
-
@jonearles:我只是想问同样的问题 :-) 我实际上尝试使用这种方法获得解决方案,但没有成功:sqlfiddle.com/#!4/c3d5d/15
-
我已经考虑过@jonearles 但这是代码的一小部分。我还需要弄清楚树的顶部是什么以及数据是否是周期性的,这些都非常容易通过 connect-by 实现。另一个问题是速度,它明显变慢了。我可能最终别无选择......
-
我很想玩这个,因为它看起来很有趣,但我很困惑。如果暂时没有人回答,你能用你的样本数据画一张树的图片吗?
-
当然@gloomy.penguin,给你:i.stack.imgur.com/r9Ziu.png。不是很复杂
标签: sql oracle hierarchy oracle11gr2 connect-by