@KenGeis 在 cmets 中提到,对于 Oracle 11g,您可以使用递归查询:
with t (p, i , q) as (
select product, ingredient, qty from test where product = 'XYZ'
union all
select product, ingredient, qty*q from test, t where product = i)
select i, sum(q) qty from t
where not exists (select 1 from test where product = i) group by i;
如果由于某些原因您需要connect by 版本,这是我的尝试:
with t1 as (
select ingredient i, sys_connect_by_path(ingredient, '/') path1,
sys_connect_by_path(qty, '/') path2
from test where connect_by_isleaf = 1 connect by prior ingredient = product
start with product = 'XYZ' ),
t2 as (
select i, path1, path2, trim(regexp_substr(path2, '[^/]+', 1, lines.column_value)) val
from t1,
table (cast (multiset(
select level from dual connect by level < regexp_count(t1.path2, '/')+1
) as sys.ODCINumberList ) ) lines)
select i, sum(s) qty
from (select i, exp(sum(ln(val))) s from t2 group by i, path1) group by i
SQL Fiddle demo for both queries
子查询t1 生成所需原料的列表,并在列 path2 中 - 我们需要相乘的因素。
t2 unpivots 这些值,最终查询执行乘法并对结果进行分组,以防万一
是两个使用相同原材料的半成品。
对于乘法,我使用了来自this SO 问题的答案。