Выберите родительские строки и включите стоимость дочерних

У меня есть таблица WORKORDER, в которой есть родительский и дочерний WO:

with workorder as (
select 'WO37342' as wonum,      null as parent, 297.36 as actlabcost, 200 as actmatcost, 0 as actservcost, 0 as acttoolcost from dual
union all
select 'WO37427' as wonum, 'WO37342' as parent,  99.12 as actlabcost,   0 as actmatcost, 0 as actservcost, 0 as acttoolcost from dual
union all
select 'WO37429' as wonum, 'WO37342' as parent,  99.12 as actlabcost, 100 as actmatcost, 0 as actservcost, 0 as acttoolcost from dual
)
select
    * 
from
    workorder

 WONUM   PARENT  ACTLABCOST ACTMATCOST ACTSERVCOST ACTTOOLCOST
 ------- ------- ---------- ---------- ----------- -----------
 WO37342             297.36        200           0           0
 WO37427 WO37342      99.12          0           0           0
 WO37429 WO37342      99.12        100           0           0

Я хочу выбрать родительские строки и включить стоимость дочерних элементов в родительские:

 WONUM    ACTLABCOST ACTMATCOST ACTSERVCOST ACTTOOLCOST
 ------- ----------- ---------- ----------- -----------
 WO37342       495.6        300           0           0

Есть ли краткий способ сделать это в Oracle 19c?

(Моя цель — сделать SQL максимально простым/удобочитаемым.)


person User1973    schedule 06.11.2020    source источник
comment
Только дети или все потомки?   -  person MT0    schedule 06.11.2020
comment
@MTO Есть только дочерний уровень. Нет потомков более низкого уровня (нет внуков и т. д.).   -  person User1973    schedule 06.11.2020


Ответы (2)


Для одноуровневых отношений родитель/дети, как показано в ваших примерах данных, я бы рекомендовал:

select  
    coalesce(parent, wonum) wonum
    sum(actlabcost)  actlabcost, 
    sum(actmatcost)  actmatcost,
    sum(actservcost) actservcost,
    sum(acttoolcost) acttoolcost
from workorder wo
group by coalesce(parent, wonum)
person GMB    schedule 06.11.2020

Для иерархии с несколькими уровнями вы можете использовать CONNECT_BY_ROOT( ... ), а затем GROUP BY, что:

SELECT root_wonum AS wonum,
       SUM( actlabcost ) AS total_actlabcost,
       SUM( actmatcost ) AS total_actmatcost,
       SUM( actservcost ) AS total_actservcost,
       SUM( acttoolcost ) AS total_acttoolcost
FROM   (
  SELECT CONNECT_BY_ROOT( wonum ) AS root_wonum,
         actlabcost,
         actmatcost,
         actservcost,
         acttoolcost
  FROM   workorder
  START WITH parent IS NULL
  CONNECT BY PRIOR wonum = parent
)
GROUP BY root_wonum;

Что для тестовых данных:

CREATE TABLE workorder ( wonum, parent, actlabcost, actmatcost, actservcost, acttoolcost ) as
select 'WO37342',      null, 297.36, 200, 0, 0 from dual union all
select 'WO37427', 'WO37342',  99.12,   0, 0, 0 from dual union all
select 'WO37429', 'WO37342',  99.12, 100, 0, 0 from dual;

Выходы:

WONUM   | TOTAL_ACTLABCOST | TOTAL_ACTMATCOST | TOTAL_ACTSERVCOST | TOTAL_ACTTOOLCOST
:------ | ---------------: | ---------------: | ----------------: | ----------------:
WO37342 |            495.6 |              300 |                 0 |                 0

db‹›fiddle здесь

person MT0    schedule 06.11.2020