2015-11-03 58 views
-3

以下是與我的真實場景類似的示例上下文。使用連接的分層查詢通過

產品:XYZ QTY:1

需要原料B,0.002和半成品項目A,0.001。生產我需要的原料J,0.1和半成品K,0.9。有產品K我以前我需要原材料G 0.004 enter code hereT 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生成所需的原材料,並在列PATH2名單 - 這是我們需要乘以因素。 t2未轉義這些值,如果 是兩個使用相同原材料的半成品,則最終查詢執行乘法和組結果。 對於乘法我用從this SO問題的答案。