17,377
社区成员
发帖
与我相关
我的任务
分享
WITH t1 AS (
SELECT 'BP127-01'HMAT FROM dual UNION ALL
SELECT 'BP127-10' FROM dual UNION ALL
SELECT '127' FROM dual
),t2 AS (
SELECT 'BP127-01'HMAT,'71(2426K)'CHLVHMAT,90 QTY FROM dual UNION ALL
SELECT 'BP127-01'HMAT,'BP127-10'CHLVHMAT,10 QTY FROM dual UNION ALL
SELECT 'BP127-10'HMAT,'127'CHLVHMAT,10 QTY FROM dual UNION ALL
SELECT 'BP127-10'HMAT,'24-1'CHLVHMAT,30 QTY FROM dual UNION ALL
SELECT 'BP127-10'HMAT,'71(2426K)'CHLVHMAT,60 QTY FROM dual UNION ALL
SELECT '127'HMAT,'24-1'CHLVHMAT,30 QTY FROM dual UNION ALL
SELECT '127'HMAT,'71(2426K)'CHLVHMAT,30 QTY FROM dual
)
SELECT LEVEL,chlvhmat,hmat,connect_by_isleaf flag,urqunty FROM (SELECT t1.hmat,t2.chlvhmat,t2.qty urqunty FROM t1,t2 WHERE t1.hmat=t2.hmat)
START WITH hmat='BP127-01'
CONNECT BY PRIOR chlvhmat=hmat
ORDER siblings BY hmat;
LEVEL, CHLVHMAT, HMAT, FLAG, URQUNTY
1 71(2426K) BP127-01 1 90
1 BP127-10 BP127-01 0 10
2 127 BP127-10 0 10
3 24-1 127 1 30
3 71(2426K) 127 1 30
2 24-1 BP127-10 1 30
2 71(2426K) BP127-10 1 60
Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.3.0
Connected as RCOTRPR1
SQL>
SQL> CREATE OR REPLACE FUNCTION cal_rate(v_level_rate IN VARCHAR2) RETURN NUMBER AS
2 v_rate NUMBER;
3 BEGIN
4 EXECUTE IMMEDIATE 'select ' || v_level_rate || ' from dual'
5 INTO v_rate;
6 RETURN v_rate;
7 END cal_rate;
8 /
Function created
SQL>
SQL> WITH t1 AS (
2 SELECT 'BP127-01'HMAT FROM dual UNION ALL
3 SELECT 'BP127-10' FROM dual UNION ALL
4 SELECT '127' FROM dual
5 ),t2 AS (
6 SELECT 'BP127-01'HMAT,'71(2426K)'CHLVHMAT,80 QTY FROM dual UNION ALL
7 SELECT 'BP127-01'HMAT,'BP127-10'CHLVHMAT,20 QTY FROM dual UNION ALL
8 SELECT 'BP127-10'HMAT,'127'CHLVHMAT,10 QTY FROM dual UNION ALL
9 SELECT 'BP127-10'HMAT,'24-1'CHLVHMAT,30 QTY FROM dual UNION ALL
10 SELECT 'BP127-10'HMAT,'71(2426K)'CHLVHMAT,60 QTY FROM dual UNION ALL
11 SELECT '127'HMAT,'24-1'CHLVHMAT,30 QTY FROM dual UNION ALL
12 SELECT '127'HMAT,'71(2426K)'CHLVHMAT,30 QTY FROM dual
13 )
14 SELECT chlvhmat, sum(cal_rate(substr(sys_connect_by_path(rate, '*'), 2))) rate FROM (
15 SELECT LEVEL lv, chlvhmat, hmat,
16 urqunty / SUM(urqunty) over(PARTITION BY LEVEL ORDER BY LEVEL) rate
17 FROM (SELECT t1.hmat, t2.chlvhmat, t2.qty urqunty FROM t1, t2 WHERE t1.hmat = t2.hmat)
18 START WITH hmat = 'BP127-01'
19 CONNECT BY PRIOR chlvhmat = hmat) WHERE connect_by_isleaf = 1
20 start with hmat='BP127-01'
21 connect by prior chlvhmat = hmat GROUP BY chlvhmat;
CHLVHMAT RATE
--------- ----------
71(2426K) 0.93
24-1 0.07
SQL>
比较取巧,因为sys_connect_by_path可以连接所有的父节点,用乘号连接变成varchar2类型,再用动态sql把乘法结果算出来,需要创建一个function.WITH t1 AS
(SELECT 'BP127-01' hmat
FROM dual
UNION ALL
SELECT 'BP127-10'
FROM dual
UNION ALL
SELECT '127' FROM dual),
t2 AS
(SELECT 'BP127-01' hmat, '71(2426K)' chlvhmat, 90 qty
FROM dual
UNION ALL
SELECT 'BP127-01' hmat, 'BP127-10' chlvhmat, 10 qty
FROM dual
UNION ALL
SELECT 'BP127-10' hmat, '127' chlvhmat, 10 qty
FROM dual
UNION ALL
SELECT 'BP127-10' hmat, '24-1' chlvhmat, 30 qty
FROM dual
UNION ALL
SELECT 'BP127-10' hmat, '71(2426K)' chlvhmat, 60 qty
FROM dual
UNION ALL
SELECT '127' hmat, '24-1' chlvhmat, 30 qty
FROM dual
UNION ALL
SELECT '127' hmat, '71(2426K)' chlvhmat, 30 qty FROM dual)
SELECT chlvhmat, SUM(urqunty) urqunty FROM (
SELECT LEVEL lv, chlvhmat, hmat, connect_by_isleaf flag,
urqunty / SUM(urqunty) over(PARTITION BY LEVEL ORDER BY LEVEL) / power(10, LEVEL - 1) urqunty
FROM (SELECT t1.hmat, t2.chlvhmat, t2.qty urqunty FROM t1, t2 WHERE t1.hmat = t2.hmat)
START WITH hmat = 'BP127-01'
CONNECT BY PRIOR chlvhmat = hmat)
WHERE flag = 1
GROUP BY chlvhmat;