展开BOM并使用最终用量的算法(转载)

摘要:
本文是子ITPUB的再版。如果您的权益受到侵犯,请及时通知我,我将立即停止侵权:网站:http://www.itpub.net/thread-1020586-1-1.htmlhttp://www.itpub.net/thread -1020772-3-1. htmlhttp://www.itpub.net/thread-1020712-1-1.htmlhttp://stackoverflow

本文系转载子ITPUB,如果有侵犯您权益的地方,烦请及时的告知与我,我即刻将停止侵权行为:

网址:http://www.itpub.net/thread-1020586-1-1.html

http://www.itpub.net/thread-1020772-3-1.html

http://www.itpub.net/thread-1020712-1-1.html

http://stackoverflow.com/questions/12221047/oracle-sql-hierarchical-query-flatten-hierarchy-and-perform-aggregation

http://stackoverflow.com/questions/4786492/help-calculating-complex-sum-in-hierarchical-dataset/4786672#4786672

LEVEL 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
A是成品
B,C,D是半成品
E,Z是原材料
从上面一个比例关系可以计算出,做一个A最终需要10.8个E和3个Z,
也就是能看到下面的结果
ParentChild QTY
A E 10.8
A Z 3
我想知道有没有什么办法通过一个SQL语句来实现这个功能。

测试表:

CREATE TABLE BOM (PARENT VARCHAR2(10),CHILD VARCHAR2(10),P_QTY NUMBER, C_QTY NUMBER);
INSERT INTO BOM VALUES ('A','B',1,3);
INSERT INTO BOM VALUES ('B','C',2,3);
INSERT INTO BOM VALUES ('C','D',5,6);
INSERT INTO BOM VALUES ('D','E',1,2);
INSERT INTO BOM VALUES ('A','Z',1,3);
COMMIT;
1、使用SQL

1 SELECT P, D, SUM(QTY)
2   FROM (SELECT P, C, D, POWER(10, SUM(LOG(10, QTY))) ASQTY
3           FROM (SELECT DISTINCTP,
4 C,
5                                 SUBSTR(C, -1, 1) D,
6                                 REGEXP_SUBSTR(C, '[^,]+', 1, LEVEL),
7                                 TO_NUMBER(REGEXP_SUBSTR(Q, '[^*]+', 1, LEVEL)) ASQTY
8                   FROM (SELECT CONNECT_BY_ROOT PARENT ASP,
9                                SUBSTR(SYS_CONNECT_BY_PATH(CHILD, ','), 2) ASC,
10                                1 || SYS_CONNECT_BY_PATH(C_QTY / P_QTY, '*') ASQ
11                           FROMBOM
12                          WHERE CONNECT_BY_ISLEAF = 1
13                          START WITH PARENT = 'A'
14                         CONNECT BY PARENT =PRIOR CHILD) C
15                 CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(Q, '[^*]', '')) + 1
16                  ORDER BY 1, 2) TT
17          GROUP BYP, C, D) FF
18  GROUP BY P, D

2、使用NEWID提供的聚合求积函数

解决思路:
1.把A的每个叶子找出来;
2.顺着叶子往根,一路作乘法上去。

1 SELECTCHILD,
2        (SELECT PROD_AGG(C_QTY) /PROD_AGG(P_QTY)
3           FROMBOM
4         CONNECT BY PRIOR PARENT =CHILD
5          START WITH CHILD = INNER.CHILD --从每个叶子开始
6         ) ASC_QTY
7   FROM (SELECT BOM.*, CONNECT_BY_ISLEAF ASIS_LEAF
8           FROMBOM
9         CONNECT BY PRIOR CHILD =PARENT
10          START WITH PARENT = 'A')
11  INNER WHERE IS_LEAF = 1 --这个条件找出所有的叶子

其中PROD_AGG 见:
http://www.itpub.net/thread-1020772-1-1.html
CHILD C_QTY
---------- ----------
E 10,8
Z 3
不用PRO_AGG的方法:

1 不用 PROD_AGG的办法:
2 SELECTCHILD
3       ,(SELECT POWER(10,SUM(LOG(10,C_QTY)))/POWER(10,SUM(LOG(10,P_QTY))) 
4           FROMBOM 
5        CONNECT BY PRIOR PARENT=CHILD 
6          START WITH CHILD = inner.CHILD     --从每个叶子开始
7         ) ASC_QTY 
8 FROM (SELECT BOM.*
9             ,CONNECT_BY_ISLEAF ASIS_LEAF  
10         FROMBOM 
11         CONNECT BY PRIOR CHILD =PARENT 
12        START WITH PARENT='A' 
13      ) inner
14 WHERE IS_LEAF=1;      --这个条件找出所有的叶子

3、使用PL/SQL的方法:可以将1替换为connect_by_isleaf:如果为叶子节点,则该函数的值1,否则为0,刚好可以替代1,

1 SELECTCHILD, GET_EXPRESSION_RSLT(CON_QTY)
2   FROM (SELECTCHILD,
3                LEVELM,
4                1 || SYS_CONNECT_BY_PATH(C_QTY / P_QTY, '*') CON_QTY
5           FROMBOM
6          WHERE CONNECT_BY_ISLEAF = 1
7          START WITH PARENT = 'A'
8         CONNECT BY PARENT = PRIOR CHILD) A

结果:
1E10.8
2F3.85714285714285714285714285714285714287
3Z3

自定义函数:

1 CREATE OR REPLACE FUNCTION GET_EXPRESSION_RSLT(I_EXPRESSION VARCHAR2) RETURN VARCHAR2 IS
2  /************************************************************
3 * 函数名称:GET_EXPRESSION_RSLT
4 * 功能描述:获取指定的表达式的结果
5 * 参数:I_EXPRESSION :表达式  例如:1*2*3
6 * 编 写 人:XXX
7 * 编写时间:XXXX-XX-XX
8 * 修改记录:
9 *************************************************************/
10     RETURNSTR VARCHAR2(500) := '';
11     EXECSQL   VARCHAR2(4000) := '';
12   BEGIN
13     EXECSQL := 'SELECT ' || I_EXPRESSION || 'FROM  DUAL';
14     EXECUTEIMMEDIATE (EXECSQL)
15       INTORETURNSTR;
16     RETURNRETURNSTR;
17   END;

如果要看A用了每个B,C,D,E
则只需要将CONNECT_BY_SILEFT=1去掉即可

也可以使用下面的语句:

1 SELECTCHILD, dbms_aw.eval_number(CON_QTY)
2   FROM (SELECTCHILD,
3                LEVELM,
4                1 || SYS_CONNECT_BY_PATH(C_QTY / P_QTY, '*') CON_QTY
5           FROMBOM
6          WHERE CONNECT_BY_ISLEAF = 1
7          START WITH PARENT = 'A'
8         CONNECT BY PARENT = PRIOR CHILD) A

其中dbms_aw.eval_number这个函数是用来解析字符串函数的

或者使用with函数

1 WITH H AS
2  (SELECT SYS_CONNECT_BY_PATH(CHILD, '/') NAVPATH,
3 CHILD,
4 QUANTITY QTY,
5 ISLEAF
6     FROMITEMHIER
7    START WITH PARENT = 'ASSY001'
8   CONNECT BY PRIOR CHILD =PARENT)
9 SELECTH1.NAVPATH, H1.CHILD,(
10 SELECT /*EXP(SUM(LN(H2.QTY))),*/
11 POWER(10, SUM(LOG(10, QTY)))
12   FROMH H2
13  WHERE INSTR(H1.NAVPATH, H2.NAVPATH) = 1) QTY
14   FROMH H1
15  WHERE ISLEAF = 1

免责声明:文章转载自《展开BOM并使用最终用量的算法(转载)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Linux 强制卸载硬盘 (Device is busy)C++ 迭代器(STL迭代器)iterator详解下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

JDBC存储过程

CallableStatement     专执行存储过程的接口,继承了Statement接口   常用方法:     boolean execute(): 执行sql语句,返回true,第一个sql语句的结果是ResultSet;否则,第一个sql语句返回的是受影响的行。     getResultSet():用于获取执行"select"语句后的查询结...

SQL Server 通过“with as”方法查询树型结构

一、with as 公用表表达式   类似VIEW,但是不并没有创建对象,WITH  AS 公用表表达式不创建对象,只能被后随的SELECT语句,其作用:   1. 实现递归查询(树形结构)   2. 可以在一个语句中多次引用公用表表达式,使其更加简洁 二、非递归的公共表达式   可以是定义列或自动列和select into 效果差不多 --指定列 wi...

Sql server --触发器

概念:   触发器(trigger)是SQL server 提供给程序员和数据分析员来保证数据完整性的一种方法,它是与表事件相关的特殊的存储过程,它的执行不是由程序调用,也不是手工启动,而是由事件来触发,当对一个表进行操作( insert,delete, update)时就会激活它执行。触发器经常用于加强数据的完整性约束和业务规则等。 触发器可以从 DBA...

postgresql 一些简单应用(分页,取前N条数据,nvl(),数据类型转换)

1.分页 select * from (   select     row_number() over() as rownum,     H.*   from tableName H ) where rownum between page1  and page2  2.取前N条数据 select * from (   select     row_numb...

利用MSSQL排序规则,查询区分大小写的数据 枫

1、查询MSSQL所有排序规则: SELECT * FROM fn_helpcollations() 2、排序规则含义说明: BIN 二进制排序CI(CS) 是否区分大小写,CI不区分,CS区分AI(AS) 是否区分重音,AI不区分,AS区分   KI(KS) 是否区分假名类型,KI不区分,KS区分 WI(WS) 是否区分宽度 WI不区分,WS区分  3...

记录: Sql 常见分页方法总结

Sql server 2005 分页使用样例, 写下备忘。 sql 分页语句 withtblinfozero--随便取个表别名as(selectartid,arttitle,author,pubtime.pubip,--筛选的字段row_number()over(orderbyartiddesc)as'rowID'/*****row_number()函数的...