使用Connect By的分层查询

时间:2015-11-03 04:08:50

标签: sql oracle oracle-ebs

下面是示例上下文,与我的实际情况类似。

产品:XYZ QTY:1

需要原材料B,0.002和半成品A,0.001。生成我需要的原材料J,0.1和半成品K,0.9。在我需要原材料G 0.004 enter code hereT 0.005

之前,请提供产品K I.

我需要获得总需要所有原材料的结果及其累计数量,以便在产品数量10中生成XYZ

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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 - 我们需要乘以的因子。 t2 unpivots 这些值,最终查询执行乘法和组结果以防万一 是两个使用相同原料的半成品。 对于乘法,我使用了来自this SO问题的答案。