В postgresql с использованием запроса
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;
мы получим стол
Как добавить в эту таблицу рассчитанную сумму затрат всех вложенных дочерних элементов? Примером этой суммы является столбец CUMULATIVE_COST
.
Представленная таблица представляет собой древовидную систему.
Столбец depth
показывает уровень вложенности.
В столбце parent_id
показан tow_id
родительского объекта.
минимальный, воспроизводимый пример:
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)
;
как вариант, нужно просуммировать cost
всех следующих строк, при этом эти строки имеют большее значение depth
, чем текущая
Я добавил код @Dogbert
Хотя это воспроизводимый пример, он не является минимальным. Количество полезных ответов на сообщение обычно обратно пропорционально размеру примера (исключая случаи отсутствия или неадекватности примеров). Включайте только столько образцов данных и примеров выходных данных, сколько необходимо для четкой демонстрации желаемого поведения.
Мне просто нужно понять куда смотреть, исключения и ошибки буду обходить сам
Код содержит множество ошибок. Для parent_id
не существует типа, а синтаксис root.xyz недействителен.
исправлены ошибки. Добавлен тип данных для parent_id
и кавычки для root.xyz
.
Присоедините таблицу обратно к самой себе с помощью оператора-предка LTREE, <@
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;
Большое спасибо! Вы помогли мне разобраться! 1. Я изменил функцию генерации на path
, чтобы она приняла форму вашего примера fullpath
2. С помощью JOIN
я нашел сумму, как в вашем примере
Что в
types_of_work
? Пожалуйста, опубликуйте минимальный воспроизводимый пример: stackoverflow.com/help/minimal-reproducible-example.