2015-11-03 5 views
-3

Ниже приведен пример контекста, похожий на мой реальный сценарий.Иерархический запрос с использованием соединения

продукта: XYZ QTY:1

потребности в сырье B,0.002 и полуфабриката A,0.001. Продукт A Требуется исходный материал J,0.1 и полуфабрикат Товар K,0.9. Имейте продукт K I до того, как мне понадобится Сырье G 0,004 enter code here и T 0.005.

Мне нужно получить итоговое количество всех необходимых материалов с его суммарными количествами для производства 10 в количестве XYZ.

+1

Должно ли решение использовать CONNECT BY? Это будет более естественным с рекурсивным предложением WITH. –

+1

Я думаю, что это хороший вопрос, но он был занижен, потому что заголовок очень общий, и проблема трудно читать. Кроме того, я не буду продолжать работу над решением, пока вы не уточните, действительно ли вам нужно использовать CONNECT BY (т. Е. Используете ли вы Oracle менее 11gR2?) –

ответ

1

Попробуйте это:

SELECT component AS material, 10 * quantity AS quantity 
    FROM (SELECT component, quantity, 
       CASE WHEN CONNECT_BY_ISLEAF = 1 THEN 'Raw' ELSE 'Semi-Finished' END AS type 
    FROM bill_of_materials 
    START WITH item = 'XYZ' CONNECT BY PRIOR component = item) 
WHERE type = 'Raw' 

Пример на SQL Fiddle дает:

J |  1 
G |  0.04 
T |  0.05 
B |  0.02 
+0

Я забыл о умножении факторов вниз по дереву. Передумает это завтра. –

1

Как уже упоминалось в комментариях по @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 - факторы, которые мы должны размножаться. t2unsivots эти значения, окончательный запрос выполняет умножение и результаты групп в случае, если были двумя полуфабрикатами, которые используют одно и то же сырье. Для умножения я использовал ответ от this SO вопрос.