Как уже упоминалось в комментариях по @KenGeis, для 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
генерирует список необходимых исходных ингредиентов и в колонке путь2 - факторы, которые мы должны размножаться. t2
unsivots эти значения, окончательный запрос выполняет умножение и результаты групп в случае, если были двумя полуфабрикатами, которые используют одно и то же сырье. Для умножения я использовал ответ от this SO вопрос.
Должно ли решение использовать CONNECT BY? Это будет более естественным с рекурсивным предложением WITH. –
Я думаю, что это хороший вопрос, но он был занижен, потому что заголовок очень общий, и проблема трудно читать. Кроме того, я не буду продолжать работу над решением, пока вы не уточните, действительно ли вам нужно использовать CONNECT BY (т. Е. Используете ли вы Oracle менее 11gR2?) –