Ran*_*ndy 2 sql oracle lag hierarchical-data
我有一个有趣的SQL问题.我有一个分层的表格来制作物料清单.与此类似:
ASSEMBLY
---------
parent_part_id
part_id
quantity
Run Code Online (Sandbox Code Playgroud)
我用这样的查询得到了这个结构的层次结构:
SELECT level, part_id, quantity
from assembly
start with parent_part_id = 1
connect by parent_part_id = prior part_id;
Run Code Online (Sandbox Code Playgroud)
输出可能如下所示:
level part_id quantity
----- ------- ---------
1 2 2
2 3 10
1 4 2
2 5 1
3 3 5
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.
问题是:如何计算顶级装配所需的每个零件的总数(第1部分)?
按部分对此结果进行分组并对数量求和是不正确的,因为数量应乘以层次结构中当前部分正上方的部分数量,递归地向上到树.
我认为这是一个LAG功能,但无法将其可视化.
编辑:预期结果:
part_id quantity
------- --------
2 2
3 30
4 2
5 2
Run Code Online (Sandbox Code Playgroud)
更多编辑:我通过此查询获得有趣的结果
SELECT rownum, level lvl, part_id, quantity, unit_of_measure
, connect_by_isleaf || sys_connect_by_path(quantity,'*') math
from assembly
start with parent_part_id = 1
connect by parent_part_id = prior part_id
Run Code Online (Sandbox Code Playgroud)
math列返回我想要执行的计算的字符串表示:)例如它可能会说:
1*1*2*10
Run Code Online (Sandbox Code Playgroud)
或类似和适当的东西...也许做一个功能来解析这个并返回结果将解决问题..谁都认为这是无耻的?
在Oracle 11 R2中它可能具有common table expression:
测试数据:
-- drop table assembly;
create table assembly (
part_id number,
parent_part_id number,
quantity number
);
insert into assembly values (2, 1, 2);
insert into assembly values (3, 2, 10);
insert into assembly values (4, 1, 2);
insert into assembly values (5, 4, 1);
insert into assembly values (3, 5, 5);
Run Code Online (Sandbox Code Playgroud)
选择声明:
select
part_id,
sum(quantity_used) as quantity
from (
with assembly_hier (lvl, part_id, quantity, quantity_used) as (
select
1 lvl,
part_id,
quantity ,
quantity quantity_used
from
assembly
where
parent_part_id = 1
union all
select
assembly_hier.lvl + 1 lvl,
assembly .part_id,
assembly .quantity,
assembly_hier.quantity_used * assembly.quantity quantity_used
from
assembly_hier, assembly
where
assembly_hier.part_id = assembly.parent_part_id
)
select * from assembly_hier
)
group by part_id
order by part_id;
Run Code Online (Sandbox Code Playgroud)
编辑在Ora11R2之前,它可能适用于model clause:
select
part_id,
sum(quantity) quantity
from (
select
lvl
parent_part_id,
part_id,
quantity
from (
select
lvl,
parent_part_id,
part_id,
quantity
from (
select
rownum r,
level lvl,
parent_part_id,
part_id,
quantity
from
assembly
start with parent_part_id = 1
connect by parent_part_id = prior part_id
)
)
model
dimension by (lvl, part_id)
measures (quantity, parent_part_id)
rules upsert (
quantity[ any, any ] order by lvl, part_id = quantity[cv(lvl) , cv(part_id)] *
nvl( quantity[cv(lvl)-1, parent_part_id[cv(lvl), cv(part_id)] ], 1)
)
)
group by part_id
order by part_id;
Run Code Online (Sandbox Code Playgroud)
编辑II另一种可能性是将数量的对数相加,然后取总和的指数:
select
part_id,
sum(quantity) quantity
from (
select
part_id,
exp(sum(quantity_ln) over (partition by new_start order by r)) quantity
from (
select
r,
lvl,
part_id,
quantity_ln,
sum(new_start) over(order by r) new_start
from (
select
rownum r,
level lvl,
part_id,
ln(quantity) quantity_ln,
nvl(lag(connect_by_isleaf,1) over (order by rownum),0) new_start
from assembly
start with parent_part_id = 1
connect by parent_part_id = prior part_id
)
)
)
group by part_id
order by part_id
;
Run Code Online (Sandbox Code Playgroud)