这个问题能解的一定是高手!

LEVEL    Parent   Chile    Parent Qty        Child Qty
1            A            B         1                       3
2            B            C         2                       3
3            C            D         5                       6
4            D            E         1                       2
1            A            Z         1                       3

A是成品
B,C,D是半成品
E,Z是原材料

从上面一个比例关系可以计算出,做一个A最终需要10.8个E和3个Z,我想知道有没有什么办法通过一个SQL语句来实现这个功能。

请大家帮忙想象办法。

[ 本帖最后由 lypch 于 2008-7-11 21:52 编辑 ]
我也来说两句 查看全部回复

最新回复

  • lypch (2008-7-11 11:15:04)

    怎么也没有人回答啊。
  • coltsu (2008-7-14 15:03:07)

    好象困难
    select 1||sys_connect_by_path(child_qty/parent_qty,'*') From table_name start with chile='E' connect by chile=prior parent;
    运行结果:
    1*2
    1*2*1.2
    1*2*1.2*1.5
    1*2*1.2*1.5*3

    1*2*1.2*1.5*3=10.8
  • yzsind (2008-7-15 10:27:10)

    create table TEST6
    (
      MYLEVEL    NUMBER,
      PARENT     VARCHAR2(1),
      CHILD      VARCHAR2(1),
      PARENT_QTY NUMBER,
      CHILD_QTY  NUMBER
    )
    ;

    insert into TEST6 (MYLEVEL, PARENT, CHILD, PARENT_QTY, CHILD_QTY)
    values (1, 'A', 'B', 1, 3);
    insert into TEST6 (MYLEVEL, PARENT, CHILD, PARENT_QTY, CHILD_QTY)
    values (2, 'B', 'C', 2, 3);
    insert into TEST6 (MYLEVEL, PARENT, CHILD, PARENT_QTY, CHILD_QTY)
    values (3, 'C', 'D', 5, 6);
    insert into TEST6 (MYLEVEL, PARENT, CHILD, PARENT_QTY, CHILD_QTY)
    values (4, 'D', 'E', 1, 2);
    insert into TEST6 (MYLEVEL, PARENT, CHILD, PARENT_QTY, CHILD_QTY)
    values (1, 'A', 'E', 1, 3);
    commit;


    SQL> select substr(p, 1, decode(instr(p, '/', 2), 0, 100, instr(p, '/', 2) - 1)) N,
      2         exp(SUM(ln(CHILD_QTY / PARENT_QTY))) V
      3    from (select CHILD_QTY,
      4                 PARENT_QTY,
      5                 SYS_CONNECT_BY_PATH(PARENT || '-' || CHILD, '/') P
      6            from test6 a
      7           start with mylevel = 1
      8          connect by PRIOR child = parent)
      9   group by substr(p,
    10                   1,
    11                   decode(instr(p, '/', 2), 0, 100, instr(p, '/', 2) - 1))
    12  ;

    N                                                                                         V
    -------------------------------------------------------------------------------- ----------
    /A-B                                                                                   10.8
    /A-E                                                                                      3

    SQL>
  • yzsind (2008-7-15 10:28:48)

    从老杨那里整理的

    http://yangtingkun.itpub.net/post/468/466388

    做了一点小的调整
  • yzsind (2008-7-15 11:38:19)

    估计楼主想要做一个BOM的分解功能,但是个人认为用一条SQL去实现这个功能比较难,楼主的例子还比较简单,如果出现一个半成品需要多个原料,或者是一个半成品A需要半成品B和一种原料C,半成品B又需要原料C时,上面的SQL就不行了。
    建议楼主还是采用PL/SQL或者是其它程序言去实现吧,这样可靠性及可读性及可维护性会好得多。
  • yzsind (2008-7-15 15:18:32)

    贴一个用PL/SQL实现BOM计算的简单算法

    create table TEST6
    (
      MYLEVEL    NUMBER,
      PARENT     VARCHAR2(10),
      CHILD      VARCHAR2(10),
      PARENT_QTY NUMBER,
      CHILD_QTY  NUMBER
    )
    ;

    insert into TEST6 (MYLEVEL, PARENT, CHILD, PARENT_QTY, CHILD_QTY)
    values (1, 'A', 'B', 1, 3);
    insert into TEST6 (MYLEVEL, PARENT, CHILD, PARENT_QTY, CHILD_QTY)
    values (2, 'B', 'C', 2, 3);
    insert into TEST6 (MYLEVEL, PARENT, CHILD, PARENT_QTY, CHILD_QTY)
    values (3, 'C', 'D', 5, 6);
    insert into TEST6 (MYLEVEL, PARENT, CHILD, PARENT_QTY, CHILD_QTY)
    values (4, 'D', 'E', 1, 2);
    insert into TEST6 (MYLEVEL, PARENT, CHILD, PARENT_QTY, CHILD_QTY)
    values (1, 'A', 'Z', 1, 3);
    insert into TEST6 (MYLEVEL, PARENT, CHILD, PARENT_QTY, CHILD_QTY)
    values (4, 'D', 'F', 1, 3);
    insert into TEST6 (MYLEVEL, PARENT, CHILD, PARENT_QTY, CHILD_QTY)
    values (3, 'C', 'F', 2, 3);
    insert into TEST6 (MYLEVEL, PARENT, CHILD, PARENT_QTY, CHILD_QTY)
    values (2, 'B', 'D', 1, 1.5);
    commit;

    --临时表,用来保存计算结果
    create global temporary table TEMP_TEST6
    (
      PARENT VARCHAR2(10),
      CHILD  VARCHAR2(10),
      QTY    NUMBER
    )
    on commit preserve rows;
  • yzsind (2008-7-15 15:19:53)

    --BOM计算的函数
    create or replace procedure CalcBOM(iPName varchar2) is
      vCnt int;
      procedure getvalue(iParent varchar2, iQty number) as
        cursor cur_test6(iParent varchar2) is
          select * from test6 where parent = iParent;
      begin
        select count(*) into vCnt from test6 where parent = iParent;
        if vCnt = 0 then
          insert into temp_test6
            (parent, child, qty)
          values
            (iPName, iParent, iQty);
          dbms_output.put_line('iParent:' || iParent || ';iValue:' || iQty);
        else
          for v_rec in cur_test6(iParent) loop
            getvalue(v_rec.child, iQty * v_rec.child_qty / v_rec.Parent_Qty);
          end loop;
        end if;
      end;
    begin
      delete from temp_test6;
      getvalue(iPName, 1);
    end CalcBOM;
  • yzsind (2008-7-15 15:25:42)

    --测试结果

    SQL> select * from test6;

       MYLEVEL PARENT     CHILD      PARENT_QTY  CHILD_QTY
    ---------- ---------- ---------- ---------- ----------
             1 A          B                   1          3
             2 B          C                   2          3
             3 C          D                   5          6
             4 D          E                   1          2
             1 A          Z                   1          3
             4 D          F                   1          3
             3 C          F                   2          3
             2 B          D                   1        1.5

    8 rows selected
    SQL> exec CalcBOM('A');

    PL/SQL procedure successfully completed
    SQL> select parent,child,sum(qty) qty from temp_test6 group by parent,child;

    PARENT     CHILD             QTY
    ---------- ---------- ----------
    A          E                19.8
    A          F               36.45
    A          Z                   3

    SQL>
  • SunnyXu (2008-7-15 17:47:17)

    为什么一定要一条sql语句?
    存储过程或函数实现不是也很好吗?  这样更容易实现。