Reputation: 73
I've ready through tons forum posts and Ask Tom pages and can't seem to find anything that works so I'm hoping you can help me out. I have a table I've created that has hierarchical data. I have the parent part number, parent price, child part number, child price, child quantity, level in the hierarchy.
Parent price always takes precedence over the sum of children - however I need to backfill where we have gaps. This is built from a root arrangement number so all level 1's are considered top level arrangements with a quantity of 1 that I need to roll up to.
I have two problems. 1) If the parent part number has a price and is also a component I need parent price x cmpnt qty to get total price 2) If the parent price is missing and all/any of the children have a price I need to "backfill" the parent price with this calculation. If only some of the children have a price I need to keep going further down the tree until I can backfill the parent.
I wrote a query but it sums all levels and my numbers where huge. I need to stop once I've successfully backfilled a level.
This is on Oracle 12C Enterprise.
Here is my test table:
--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
);
My data:
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;
Output: Select * from 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
My expected rollup would be something like:
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
EDIT: Here is the query I've been working with
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
Upvotes: 2
Views: 1659
Reputation: 52675
At first glance this seems like a fairly standard Connect_by_root and sum.
However the tricky part of your problem is 1A4 because you need to multiply the quantity of 2 by the children component values. SUM(COALESCE(PRIOR_CHILD_QTY,1) * CHILD_QTY *CHILD_PRC)
solves that.
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
Upvotes: 1
Reputation: 1819
You might try this :
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_
Upvotes: 0