本文系转载子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,
也就是能看到下面的结果
Parent  Child   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))) AS QTY
  3. FROM (SELECT DISTINCT P,
  4. C,
  5. SUBSTR(C, -1, 1) D,
  6. REGEXP_SUBSTR(C, '[^,]+', 1, LEVEL),
  7. TO_NUMBER(REGEXP_SUBSTR(Q, '[^*]+', 1, LEVEL)) AS QTY
  8. FROM (SELECT CONNECT_BY_ROOT PARENT AS P,
  9. SUBSTR(SYS_CONNECT_BY_PATH(CHILD, ','), 2) AS C,
  10. 1 || SYS_CONNECT_BY_PATH(C_QTY / P_QTY, '*') AS Q
  11. FROM BOM
  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 BY P, C, D) FF
  18. GROUP BY P, D

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

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

  1. SELECT CHILD,
  2. (SELECT PROD_AGG(C_QTY) / PROD_AGG(P_QTY)
  3. FROM BOM
  4. CONNECT BY PRIOR PARENT = CHILD
  5. START WITH CHILD = INNER.CHILD -- 从每个叶子开始
  6. ) AS C_QTY
  7. FROM (SELECT BOM.*, CONNECT_BY_ISLEAF AS IS_LEAF
  8. FROM BOM
  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. SELECT CHILD
  3. ,(SELECT POWER(10,SUM(LOG(10,C_QTY)))/POWER(10,SUM(LOG(10,P_QTY)))
  4. FROM BOM
  5. CONNECT BY PRIOR PARENT=CHILD
  6. START WITH CHILD = inner.CHILD -- 从每个叶子开始
  7. ) AS C_QTY
  8. FROM (SELECT BOM.*
  9. ,CONNECT_BY_ISLEAF AS IS_LEAF
  10. FROM BOM
  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. SELECT CHILD, GET_EXPRESSION_RSLT(CON_QTY)
  2. FROM (SELECT CHILD,
  3. LEVEL M,
  4. 1 || SYS_CONNECT_BY_PATH(C_QTY / P_QTY, '*') CON_QTY
  5. FROM BOM
  6. WHERE CONNECT_BY_ISLEAF = 1
  7. START WITH PARENT = 'A'
  8. CONNECT BY PARENT = PRIOR CHILD) A

结果:
1 E 10.8
2 F 3.85714285714285714285714285714285714287
3 Z 3

自定义函数:

  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. EXECUTE IMMEDIATE (EXECSQL)
  15. INTO RETURNSTR;
  16. RETURN RETURNSTR;
  17. END;

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

也可以使用下面的语句:

  1. SELECT CHILD, dbms_aw.eval_number(CON_QTY)
  2. FROM (SELECT CHILD,
  3. LEVEL M,
  4. 1 || SYS_CONNECT_BY_PATH(C_QTY / P_QTY, '*') CON_QTY
  5. FROM BOM
  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. FROM ITEMHIER
  7. START WITH PARENT = 'ASSY001'
  8. CONNECT BY PRIOR CHILD = PARENT)
  9. SELECT H1.NAVPATH, H1.CHILD,(
  10. SELECT /*EXP(SUM(LN(H2.QTY))),*/
  11. POWER(10, SUM(LOG(10, QTY)))
  12. FROM H H2
  13. WHERE INSTR(H1.NAVPATH, H2.NAVPATH) = 1) QTY
  14. FROM H H1
  15. WHERE ISLEAF = 1

展开BOM并使用最终用量的算法(转载)的更多相关文章

  1. Facebook开源时间序列内存数据库Beringei,追求极致压缩率——如果是int根据大多数时间序列中的值与相邻数据点相比并没有显著的变化,只要使用XOR将当前值与先前值进行比较,然后存储发生变化的比特。最终,该算法将整个数据集至少压缩了90%

    转自:http://www.infoq.com/cn/news/2017/02/Facebook-Beringei 2017年2月3日,Facebook宣布将开源他们的高性能时序数据存储引擎Berin ...

  2. A* 寻路算法[转载]

    A* 寻路算法 转载地址:http://www.cppblog.com/christanxw/archive/2006/04/07/5126.html 原文地址: http://www.gamedev ...

  3. AStar算法(转载)

    以下的文章来至http://blog.csdn.net/debugconsole/article/details/8165530,感激这位博主的翻译,可惜图片被和谐了,所以为方便阅读,我重新把图片贴上 ...

  4. 调用sklearn包中的PLA算法[转载]

    转自:https://blog.csdn.net/u010626937/article/details/72896144#commentBox 1.Python的机器学习包sklearn中也包含了感知 ...

  5. Rsync实现文件同步的算法(转载)

    Rsync文件同步的核心算法 文章出处:http://coolshell.cn/articles/7425.html#more-7425 rsync是unix/linux下同步文件的一个高效算法,它能 ...

  6. 数据结构图之三(最短路径--迪杰斯特拉算法——转载自i=i++

    数据结构图之三(最短路径--迪杰斯特拉算法)   [1]最短路径 最短路径?别乱想哈,其实就是字面意思,一个带边值的图中从某一个顶点到另外一个顶点的最短路径. 官方定义:对于内网图而言,最短路径是指两 ...

  7. FP-Tree -关联规则挖掘算法(转载)

    在关联规则挖掘领域最经典的算法法是Apriori,其致命的缺点是需要多次扫描事务数据库.于是人们提出了各种裁剪(prune)数据集的方法以减少I/O开支 支持度和置信度 严格地说Apriori和FP- ...

  8. GJM : 数据结构 - 轻松看懂机器学习十大常用算法 [转载]

     转载请联系原文作者 需要获得授权,非法转载 原文作者将享受侵权诉讼 文/不会停的蜗牛(简书作者)原文链接:http://www.jianshu.com/p/55a67c12d3e9 通过本篇文章可以 ...

  9. 浅谈MySQL索引背后的数据结构及算法(转载)

    转自:http://blogread.cn/it/article/4088?f=wb1 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储 ...

随机推荐

  1. DEV控件之ChartControl用法

    一.总体概述 这个控件包含3层,最外面的chartControl层.中间的XYDiagram层.最里面的Series层.功能非常强大,但同时使用起来也相对复杂,需要各个层之间相互协调设置才能达到自己想 ...

  2. HTML行类元素与块级元素

    在html中大部分标签都可以分为行类与块级元素,其中两者的区别是块级元素会自动换行,可设置高度与宽度:而行类元素则是连着一行写,可设置高度但是不能设置宽度. html中行类元素: a - 锚点abbr ...

  3. C#去掉字符串中的汉字

    string str = "测试一下ilove中国so结束"; Regex reg = new Regex(@"[\u4e00-\u9fa5]"); Label ...

  4. 2014.12.01 B/S 使用VS建立Web网站

    要求:从hr数据库info表读取数据,在Web网站中显示为如图: 用DW绘制一个表格,然后将代码拷贝到新建的网站主页代码中 <div> <table bgcolor=" w ...

  5. java enum的用法

    原始的常量定义: public static fianl MON=“Mon”; public static final TUE="Tue"; 语法(定义) 创建枚举类型要使用 en ...

  6. ecshop二次开发之购物车常见问题

    1.ecshop二次开发中保存注册用户购物车数据解决方法:ecshop购物车是数据库中cart表来支持的,在ecshop表中rec_id是编号,user_id是注册用户的id,session_id表示 ...

  7. QF——关于iOS的强引用,弱引用及strong,retain,copy,weak,assignd的关系

    强引用和弱引用: 我们已经知道OC中的内存管理是通过“引用计数器”来实现的.一个对象的生命周期取决于它是否还被其他对象引用(是否retainCount=0).但在有些情况下,我们并不希望对象的销毁时间 ...

  8. mysql获取各种日期

    select curdate(); --获取当前日期 select last_day(curdate()); --获取当月最后一天. select DATE_ADD(curdate(),interva ...

  9. text-indent: -999px;是什么意思

    就是把该元素内的文字移到屏幕外面去,让我们肉眼看不见,有时候是因为如某栏目名称的文字或者logo的文字已经用背景图片代替了,我们不需要眼睛看见那些文字,但是希望搜索引擎可以搜到,就可以用这个把文字“隐 ...

  10. hdu 5046 Airport 二分+重复覆盖

    题目链接 给n个点, 定义两点之间距离为|x1-x2|+|y1-y2|. 然后要选出k个城市建机场, 每个机场可以覆盖一个半径的距离. 求在选出点数不大于k的情况下, 这个半径距离的最大值. 二分半径 ...