-1

So I have written a query to get the cumulative sum of children but I think partition sum has error as its totalling for the parent that is not part of the children.

My fiddle is http://sqlfiddle.com/#!15/88828/1 I have dont a running total but thats wrong. I want the siblings total to a child and child total back to its parent.So basically cumulative total of a child up the tree.

expected output

    parent_child_tree   id  name    dimensionvalueid    level   order_sequence  volume  cummulative_total
  A1                     1  A1        (null)              0       1              20     840
-----A1:1                2  A1:1       1                  1       1_1           (null)  820
----------A1:1:1         3  A1:1:1     2                  2       1_1_2          20     820
-----------A1:1:1:1      4  A1:1:1:1   3                  3       1_1_2_3        300    800
-----------A1:1:1:2      5  A1:1:1:2.  3                  3       1_1_2_3        500    500
B1                       6  B1        (null)              0       6              200    300
-----B1:2                8  B1:2       6                  1       6_6           (null)  null
-----B1:1                7  B1:1       6                  1       6_6           (null)  100
----------B1:2:1         9  B1:2:1     8                  2       6_6_8         100     100

enter image description here

JyotiChhetri
  • 289
  • 1
  • 7
  • 21
  • Can you provide the *expected* output? Is it true that `dimensionvalueid` both serves as a parent-reference, and as a link to the volume? It is really right that siblings always have the same volume, as they share the same parent? And is it really right then that these duplicate volumes of siblings are summed up and associated to the parent? – trincot Aug 15 '22 at 16:27
  • @trincot I have updated the output, yes the dimensionvalueid serves as parent reference. Yes the parents is sum of its children as well as own value. The problem is that B1 is sum of B1:1 and B1:2:1 but B1:2 is child of B1 which has no value which should stay null – JyotiChhetri Aug 15 '22 at 16:37
  • OK, but my point is that siblings would have the same volume (I am not even looking at the aggregation). That looks strange to me. It is weird that the same volume finds its way to two siblings, like A1:1:1:1 and A1:1:1:2. – trincot Aug 15 '22 at 16:44
  • As to the aggregation, you cannot expect a running sum to solve this. This is not a running sum problem. The problem is that the second argument to `left` should be dynamic and not 1, but that highlights that this is not a running sum. – trincot Aug 15 '22 at 16:44
  • @trincot Please can you guide me to achieve the results. The child volume needs to be cumulative upto its root parent. – JyotiChhetri Aug 15 '22 at 16:46
  • 1
    But can you please confirm this strange thing about volumes applying to nodes in such a way that siblings always have the same volume (I'm not including the children yet)? It is weird why two siblings could not have different proper volumes... Are you really sure this is how it should work?? – trincot Aug 15 '22 at 19:25
  • @trincot we want to cumulate the children volume to its parent. Yes the children will sum will be added to parent, but in the example the B1 should be 100 , B1:1 should be 100 and B1:2:1 is 100. B1:2 has no volume so is null for now. If B1:2 had 200 colume then B1 would be 300 – JyotiChhetri Aug 16 '22 at 01:27
  • @trincot I have changed the expected output , for clarity. – JyotiChhetri Aug 16 '22 at 04:53
  • I have twice pointed to the "problem" of siblings having the same proper volume assigned to them (before accumulating) and twice you answer saying that volumes accumulate to their parents. That is *not* what I am pointing at. The changed expected output puzzles me more, as now it no longer corresponds to the data in fiddle. – trincot Aug 16 '22 at 04:58
  • @trincot I dont understand why is volume an issue , a volume can be anything a user assigns. A volume can be 100 or 10000. I was looking at cumulative sum of child nodes up the parent. – JyotiChhetri Aug 16 '22 at 05:01
  • *"I was looking at cumulative sum..."*: please.... my point is to *first* understand the logic of the individual volumes before looking at the cumulative sums. And it makes no sense to me. After you changed the expected output, it seems impossible to me that you could get a different volume for A:1:1:1 and A:1:1:2 (300 and 500). Where do these volumes come? It is clear in the query that the individual volume (**before accumulation**) retrieved from the table **must** be the same for both as they both have the same `dimensionvalueid`. If we cannot discuss this point, then I give up. – trincot Aug 16 '22 at 05:05
  • @trincot I have added a picture for what I was looking for. The value represents the volume, each child will have a volume or not (volume can be any number even negative number). I was looking to add the volume from bottom of the child to its immediate parents and then the volume totaling up to its parent. The dimensionvalueid represents the parent id for dimensionvalue table. A valuation table has the volume for each dimensionvalue. Dimension value table is in hierarchical relation. We have valuation that belongs to dimensionvalue table. – JyotiChhetri Aug 16 '22 at 05:12
  • @trincot I have updated fiddle also. – JyotiChhetri Aug 16 '22 at 05:21
  • I looked at the fiddle and I still see 200 volume for both A:1:1:1 and A:1:1:2, which is still illustrating my point. I have no answer to that point. Yes "A valuation table has volume for each dimensionvalue", but your items are keyed by `id`, not by `dimensionvalue`, and so (I can only repeat the same thing over and over again) sibling nodes have the **same** volume associated to them. I don't think you understand what I am saying. The image is something you cannot represent with your schema. I you disagree, please show. – trincot Aug 16 '22 at 06:46

1 Answers1

1

To get totals for tree nodes you need to generate hierarchy tree for every node in a subquery like this

SELECT
    d.*,
    v.volume,
    (
        WITH RECURSIVE cte AS (
                SELECT 
                    dd.id AS branch_id,
                    dd.id
                FROM dimensionvalue dd
                WHERE dd.id = d.id
                UNION ALL
                SELECT
                    cte.branch_id,
                    dd.id
                FROM dimensionvalue dd
                JOIN cte ON dd.dimensionvalueid = cte.id
        )
        SELECT SUM(v.volume)
        FROM cte
        JOIN valuation v ON v.dimensionvalueid = cte.id
        GROUP BY cte.branch_id
    ) AS totals
FROM dimensionvalue d
LEFT JOIN valuation v ON v.dimensionvalueid = d.id
ORDER BY d.name;

If you really need all those "decoration" columns that you generate in your query for each tree node than you can combine your recursive CTE hierarchy with subquery for totals calculation like this

WITH RECURSIVE hierarchy AS (
    SELECT
    d.id,
    d.name,
    d.dimensionvalueid,
    0 AS level,
        CAST(d.id AS varchar(50)) AS order_sequence
    FROM dimensionvalue d
    WHERE d.dimensionvalueid IS NULL
    UNION ALL
    SELECT
    e.id,
    e.name,
    e.dimensionvalueid,
    hierarchy.level + 1 AS level,
    CAST(hierarchy.order_sequence || '_' || CAST(hierarchy.id AS VARCHAR(50)) AS VARCHAR(50)) AS order_sequence
    FROM hierarchy
    JOIN dimensionvalue e ON e.dimensionvalueid = hierarchy.id
)
SELECT
    RIGHT('-----------', h.level * 5) || h.name || ' ' AS parent_child_tree, 
    h.*,
    v.volume,
    (
        WITH RECURSIVE cte AS (
                SELECT 
                    dd.id AS branch_id,
                    dd.id
                FROM dimensionvalue dd
                WHERE dd.id = h.id
                UNION ALL
                SELECT
                    cte.branch_id,
                    dd.id
                FROM dimensionvalue dd
                JOIN cte ON dd.dimensionvalueid = cte.id
        )
        SELECT SUM(v.volume)
        FROM cte
        JOIN valuation v ON v.dimensionvalueid = cte.id
        GROUP BY cte.branch_id
    ) AS totals
FROM hierarchy h
LEFT JOIN valuation v ON v.dimensionvalueid = h.id
ORDER BY h.name

You can check a working demo here

Alexey
  • 2,439
  • 1
  • 11
  • 15