有条件的汇总在Oracle中的分层表汇总?

时间:2015-09-24 20:02:35

标签: sql oracle

我已准备好通过吨论坛帖子和问汤姆页面,似乎找不到任何有用的东西,所以我希望你能帮助我。我有一个我创建的具有分层数据的表。我有层次结构中的父部件号,父价格,子部件号,子价,子数量,级别。

父母价格总是优先于儿童的总和 - 但是我需要回填我们有差距的地方。这是根据根编号构建的,因此所有级别1都被视为最高级别的安排,数量为1,我需要进行汇总。

我有两个问题。 1)如果父部件号具有价格且也是一个部件,我需要父价格x cmpnt数量来获得总价 2)如果父母价格缺失且所有/任何一个孩子都有价格,我需要用这个计算“回填”母价。如果只有一些孩子有价格,我需要继续往树下走,直到我可以回填父母。

我写了一个查询,但它总结了所有级别和我的数字。一旦我成功回填了一个级别,我就需要停止。

这是在Oracle 12C Enterprise上。

这是我的测试表:

--DROP TABLE cost_rollup;

CREATE TABLE cost_rollup
(
 parent_no VARCHAR2 (4 BYTE),
 parent_prc NUMBER,
 child_no VARCHAR2 (4 BYTE),
 child_prc NUMBER,
 child_qty NUMBER,
 level_ NUMBER
);

我的数据:

INSERT INTO cost_rollup
 VALUES ('1A1',NULL, '2A1', 0.35, 4, 1);

INSERT INTO cost_rollup
 VALUES ('1A1', NULL, '2A2', 1, 2, 1);

INSERT INTO cost_rollup
 VALUES ('1A1', NULL, '2A3', 1.25, 1, 1);

INSERT INTO cost_rollup
 VALUES ('1A2', 3, '2A4', 0.27, 1, 1);

INSERT INTO cost_rollup
 VALUES ('1A2', 3, '2A5', 0.3, 2, 1);

INSERT INTO cost_rollup
 VALUES ('1A3', NULL, '2A6', 25, 1, 1);

INSERT INTO cost_rollup
 VALUES ('1A3', NULL, '2A7', 2, 2, 1);

INSERT INTO cost_rollup
 VALUES ('1A4', NULL, '2A8', NULL, 2, 1);

INSERT INTO cost_rollup
 VALUES ('2A8', NULL, '3A1', 3, 1, 2);

INSERT INTO cost_rollup
 VALUES ('2A8', NULL, '3A2', 2, 2, 2);

INSERT INTO cost_rollup
 VALUES ('1A5', NULL, '2A9', 0.5, 4, 1);

INSERT INTO cost_rollup
 VALUES ('1A5', NULL, '2A10', NULL, 1, 1);

INSERT INTO cost_rollup
 VALUES ('2A10', NULL, '3A3', 2, 5, 2);

 COMMIT;

输出:     从cost_rollup中选择*;

PARENT_NO   PARENT_PRC  CHILD_NO    CHILD_PRC   CHILD_QTY   LEVEL_
1A1                     2A1          0.35        4          1
1A1                     2A2          1           2          1
1A1                     2A3          1.25        1          1
1A2         3           2A4          0.27        1          1
1A2         3           2A5          0.3         2          1
1A3                     2A6          25          1          1
1A3                     2A7          2           2          1
1A4                     2A8                      2          1
2A8                     3A1          3           1          2
2A8                     3A2          2           2          2
1A5                     2A9          0.5         4          1
1A5                     2A10                     1          1
2A10                    3A3          2           5          2

我预期的汇总类似于:

Parent          parent_price      level
1A1                4.65           1
1A2                3.00           1
1A3                29.00          1  
1A4                14.00          1 
2A8                7.00           2
1A5                12.00          1
2A10               10.00          2

编辑:这是我一直在使用的查询

WITH b
     AS (    SELECT CONNECT_BY_ROOT child_no root,
                    child_no,
                    parent_no,
                    level_,
                    parent_prc,
                    child_prc * child_qty AS VALUE
               FROM cost_rollup
         START WITH parent_no = '1A1'
         CONNECT BY parent_no = PRIOR child_no)
  SELECT parent_no,
     CASE
        WHEN parent_prc IS NOT NULL THEN AVG (parent_prc)
        ELSE SUM (VALUE)
     END
        prc
FROM b
GROUP BY parent_no, parent_prc

2 个答案:

答案 0 :(得分:1)

乍一看,这似乎是一个相当标准的Connect_by_root和sum。

然而,问题的棘手部分是1A4,因为您需要将2的数量乘以子组件值。 SUM(COALESCE(PRIOR_CHILD_QTY,1) * CHILD_QTY *CHILD_PRC)解决了这个问题。

with Flattened as (
select
   connect_by_root parent_no rootParent,  
   PARENT_PRC,
   CHILD_PRC,
   CHILD_QTY,
   prior CHILD_QTY prior_CHILD_QTY,
   level lvl


 FROM
   cost_rollup
   connect by prior child_no = parent_no
)

SELECT
  rootParent Parent,
  COALESCE(MIN(PARENT_PRC),
        SUM(COALESCE(PRIOR_CHILD_QTY,1) * CHILD_QTY *CHILD_PRC)) parent_price,
        MAX(lvl) as "Level"
FROM
    Flattened
Group by rootParent
ORDER BY rootParent

Demo

答案 1 :(得分:0)

你可以试试这个:

SELECT parent_no,sum(parent_price) parent_price,level_
FROM(
        SELECT parent_no,
            (child_qty * child_prc) parent_price,level_
        FROM cost_rollup
    ) t
GROUP BY parent_no,level_