In postgresql using query
WITH RECURSIVE rel_rec AS (
SELECT
1 AS depth,
*,
ARRAY[lvl] AS child_path
FROM types_of_work
WHERE parent_id IS NULL AND project_id = 14
UNION ALL
SELECT
nlevel(r.path) + 1,
n.*,
r.child_path || n.lvl
FROM rel_rec AS r
JOIN types_of_work AS n ON n.parent_id = r.tow_id
WHERE r.project_id = 14
)
SELECT
t0.tow_id,
t0.project_id,
t0.path,
t0.child_path,
t0.lvl,
t0.parent_id,
t0.depth,
t2.tow_cost
FROM rel_rec t0
LEFT JOIN (
SELECT
tow_id,
tow_cost,
tow_cost_percent,
tow_date_start,
tow_date_finish
FROM tows_contract
WHERE contract_id = 10
) AS t2 ON t0.tow_id = t2.tow_id
ORDER BY t0.child_path, t0.lvl;
we get a table
tow_id integer | path ltree | child_path smallint[] | lvl smallint | parent_id integer | depth integer | cost numeric | CUMULATIVE_COST |
---|---|---|---|---|---|---|---|
39 | root | {1} | 1 | null | 1 | ∑ 90 | |
40 | root.39 | {1,2} | 2 | 39 | 2 | 10 | |
131 | root.39 | {1,3} | 3 | 39 | 2 | 10 | |
41 | root.39 | {1,4} | 4 | 39 | 2 | 10 | |
46 | root.39 | {1,5} | 5 | 39 | 2 | ∑ 60 | |
47 | root.39.46 | {1,5,6} | 6 | 46 | 3 | ∑ 30 | |
48 | root.39.46.47 | {1,5,6,7} | 7 | 47 | 4 | ∑ 10 | |
134 | root.39.46.47.48 | {1,5,6,7,8} | 8 | 48 | 5 | 10 | |
49 | root.39.46.47 | {1,5,6,9} | 9 | 47 | 4 | 10 | |
125 | root.39.46.47 | {1,5,6,10} | 10 | 47 | 4 | 10 | |
132 | root.39.46 | {1,5,11} | 11 | 46 | 3 | ∑ 20 | |
133 | root.39.46.132 | {1,5,11,12} | 12 | 132 | 4 | 10 | |
135 | root.39.46.132 | {1,5,11,13} | 13 | 132 | 4 | 10 | |
136 | root.39.46 | {1,5,14} | 14 | 46 | 3 | ∑ 10 | |
657 | root.39.46.136 | {1,5,14,15} | 15 | 136 | 4 | 10 | |
142 | root | {16} | 16 | null | 1 | ∑ 30 | |
143 | root.142 | {16,17} | 17 | 142 | 2 | ∑ 30 | |
178 | root.142.143 | {16,17,18} | 18 | 143 | 3 | 10 | |
146 | root.142.143 | {16,17,19} | 19 | 143 | 3 | 10 | |
147 | root.142.143 | {16,17,20} | 20 | 143 | 3 | 10 | |
42 | root | {21} | 21 | null | 1 | ∑ 10 | |
43 | root.39.42 | {21,22} | 22 | 42 | 2 | ∑ 10 | |
45 | root.39.42.43 | {21,22,23} | 23 | 43 | 3 | ∑ 10 | |
671 | root.39.42.43.45 | {21,22,23,24} | 24 | 45 | 4 | ∑ 10 | |
672 | root.39.42.43.45.671 | {21,22,23,24,25} | 25 | 671 | 5 | 10 |
How to add the calculated sum of the costs of all nested children to this table? An example of this sum is the CUMULATIVE_COST
column.
The table presented is a tree system.
The depth
column shows the nesting level
The parent_id
column shows the tow_id
of the parent entity
minimal, reproducible example:
CREATE TABLE types_of_work (
tow_id integer,
path ltree,
lvl integer,
project_id integer,
parent_id integer
);
CREATE TABLE tows_contract (
tow_id integer,
cost integer,
contract_id integer
);
INSERT INTO types_of_work (tow_id, path, project_id, lvl, parent_id)
VALUES (39, 'root', 14, 1, null),
VALUES (40, 'root.39', 14, 2, 39),
VALUES (131, 'root.39', 14, 3, 39),
VALUES (41, 'root.39', 14, 5, 39),
VALUES (46, 'root.39', 14, 5, 39),
VALUES (47, 'root.39.46', 14, 6, 46),
VALUES (48, 'root.39.46.47', 14, 7, 47),
VALUES (134, 'root.39.46.47.48', 14, 8, 48),
VALUES (49, 'root.39.46.47', 14, 9, 47),
VALUES (125, 'root.39.46.47', 14, 10, 47),
VALUES (132, 'root.39.46', 14, 11, 46),
VALUES (133, 'root.39.46.132', 14, 12, 132),
VALUES (135, 'root.39.46.132', 14, 13, 132),
VALUES (136, 'root.39.46', 14, 14, 46),
VALUES (657, 'root.39.46.132', 14, 15, 136),
VALUES (142, 'root', 14, 16, null),
VALUES (143, 'root.142', 14, 17, 142),
VALUES (178, 'root.142.143', 14, 18, 143),
VALUES (146, 'root.142.143', 14, 19, 143),
VALUES (147, 'root.142.143', 14, 20, 143),
VALUES (42, 'root', 14, 21, null),
VALUES (43, 'root.42', 14, 22, 42),
VALUES (45, 'root.42.43', 14, 23, 43),
VALUES (671, 'root.42.43.45', 14, 24, 45),
VALUES (672, 'root.42.43.45.671', 14, 25, 671)
;
INSERT INTO tows_contract (tow_id, cost, contract_id)
VALUES (40, 10, 10),
VALUES (131, 10, 10),
VALUES (41, 10, 10),
VALUES (134, 10, 10),
VALUES (49, 10, 10),
VALUES (125, 10, 10),
VALUES (133, 10, 10),
VALUES (135, 10, 10),
VALUES (657, 10, 10),
VALUES (178, 10, 10),
VALUES (146, 10, 10),
VALUES (147, 10, 10),
VALUES (672, 10, 10)
;
as an option, you need to sum up the cost
of all the following lines, while these lines have a greater depth
value than the current one
Join the table back to itself with the LTREE ancestor operator, <@
with costs as (
select t.*, c.cost, c.contract_id, t.path||t.tow_id::text as fullpath
from types_of_work t
left join tows_contract c on c.tow_id = t.tow_id
)
select l.*, sum(r.cost) as cumulative_cost
from costs l
join costs r on r.fullpath <@ l.fullpath
group by l.tow_id, l.path, l.fullpath, l.project_id, l.lvl, l.parent_id,
l.cost, l.contract_id
order by l.path;