The following SQL:
WITH vehicle_build_structure (part_no, parent_part, qty_per_assembly) AS (
SELECT 'LORRY', '*', null FROM dual UNION -- if it makes things easier, you may substitute "null" for "1"
SELECT 'AXLEA', 'LORRY', 3 FROM dual UNION
SELECT 'BRAKEPAD', 'AXLEA', 2 FROM dual UNION
SELECT 'WHEEL', 'AXLEA', 4 FROM dual UNION
SELECT 'CAR', '*', null FROM dual UNION
SELECT 'AXLEB', 'CAR', 2 FROM dual UNION
SELECT 'BRAKEPAD', 'AXLEB', 2 FROM dual UNION
SELECT 'WHEEL', 'AXLEB', 2 FROM dual
), exploded_structure AS (
SELECT level lev, CONNECT_BY_ROOT s.part_no top_level_part, s.part_no, s.qty_per_assembly,
(
SELECT sum (sp.qty_per_assembly)
FROM vehicle_build_structure sp
START WITH sp.part_no = s.part_no
CONNECT BY prior sp.parent_part = sp.part_no
) sum_of_structure,
(
SELECT exp(sum(ln(sp.qty_per_assembly)))
FROM vehicle_build_structure sp
START WITH sp.part_no = s.part_no
CONNECT BY prior sp.parent_part = sp.part_no
) product_of_structure
FROM vehicle_build_structure s
START WITH s.parent_part = '*'
CONNECT BY prior s.part_no = s.parent_part
)
SELECT e.lev, e.top_level_part, e.part_no, e.qty_per_assembly,
e.sum_of_structure, e.product_of_structure
FROM exploded_structure e
Produces the following grid:
LEV TOP_LEVE PART_NO QTY_PER_ASSEMBLY SUM_OF_STRUCTURE PRODUCT_OF_STRUCTURE
---------- -------- -------- ---------------- ---------------- --------------------
1 CAR CAR
2 CAR AXLEB 2 2 2
3 CAR BRAKEPAD 2 9 24
3 CAR WHEEL 2 11 48
1 LORRY LORRY
2 LORRY AXLEA 3 3 3
3 LORRY BRAKEPAD 2 9 24
3 LORRY WHEEL 4 11 48
But I need it to produce this grid:
LEV TOP_LEVE PART_NO QTY_PER_ASSEMBLY SUM_OF_STRUCTURE PRODUCT_OF_STRUCTURE
---------- -------- -------- ---------------- ---------------- --------------------
1 CAR CAR
2 CAR AXLEB 2 2 2
3 CAR BRAKEPAD 2 4 4
3 CAR WHEEL 2 4 4
1 LORRY LORRY
2 LORRY AXLEA 3 3 3
3 LORRY BRAKEPAD 2 5 6
3 LORRY WHEEL 4 7 12
In other words, I need the SQL to tell me that when I build a Car, I need 4 wheels, and that when I build a Lorry I need 12 wheels.
However, because the part WHEEL is part of both the CAR and LORRY structures, the internal connect-by-prior statement is working its way back up both branches, and multiplying the quantities of both structures together (12 * 4 = 48). Obviously when the structure gets very complex this ends up giving me a wildly incorrect answer.
I can't work out how to limit that internal connect-by-prior statement to only work its way back up the branch from where it came.
Can anyone help?