【问题标题】:Conditional sum roll up of hierarchical table in Oracle?Oracle中分层表的条件汇总?
【发布时间】:2015-09-24 20:02:34
【问题描述】:

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

父价格总是优先于子价格的总和 - 但是我需要在我们有差距的地方补上。这是从根排列编号构建的,因此所有级别 1 都被视为顶级排列,我需要汇总到 1。

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

我写了一个查询,但它汇总了所有级别和我的数字很大。成功回填关卡后,我需要停下来。

这是在 Oracle 12C 企业版上。

这是我的测试表:

--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

【问题讨论】:

  • 您是否尝试过通过先前的分层功能使用连接?
  • 是的,我玩过它,但我不知道如何使用这些条件。如果孩子失踪,我只需要它来求和,在 1A5 的情况下,我需要使用 2A9 的 1 级价格和 2A10 的孩子价格,即 3A3,然后将所有这些价格滚动到 1A5

标签: sql oracle


【解决方案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

【讨论】:

  • 这很聪明!谢谢 - 此查询如何知道何时停止?继续使用示例行 1A4,假设 3A2 没有价格,您必须去找它的孩子——这是否仍会将所有这些成本滚动到 1A4?基本上只要 1A4 的孩子可以通过尽可能少的关卡来弥补他们的成本。
【解决方案2】:

你可以试试这个:

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_

【讨论】:

  • 我想,我误解了这个问题。我会尽快编辑答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-25
  • 1970-01-01
  • 2013-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多