Используйте коррелированный иерархический запрос (вы можете коррелировать либо по столбцу id
, либо по псевдостолбцу ROWID
):
SELECT id,
COALESCE(
col1,
(
SELECT SUM( COALESCE( col1, 0 ) )
FROM table_name s
START WITH s.ROWID = t.ROWID
CONNECT BY source_id = PRIOR id
)
) AS col1,
source_id
FROM table_name t;
Итак, для ваших данных образца:
CREATE TABLE table_name ( id, col1, source_id ) AS
SELECT 'a1', 765.3, 'a5' FROM DUAL UNION ALL
SELECT 'a2', 3298.3, 'a4' FROM DUAL UNION ALL
SELECT 'a3', 8762.1, 'a8' FROM DUAL UNION ALL
SELECT 'a4', 3298.3, null FROM DUAL UNION ALL
SELECT 'a5', null, 'a6' FROM DUAL UNION ALL
SELECT 'a6', null, null FROM DUAL UNION ALL
SELECT 'a7', 10, 'a5' FROM DUAL;
Это выводит:
ID | COL1 | SOURCE_ID
:- | -----: | :--------
a1 | 765.3 | a5
a2 | 3298.3 | a4
a3 | 8762.1 | a8
a4 | 3298.3 | <em>null</em>
a5 | 775.3 | a6
a6 | 775.3 | <em>null</em>
a7 | 10 | a5
Вам может потребоваться прекратить итерацию, когда вы найдете первое ненулевое значение в каждой ветви иерархии. Для этого просто потребуется добавить простой фильтр:
SELECT id,
COALESCE(
col1,
(
SELECT SUM( COALESCE( col1, 0 ) )
FROM table_name s
START WITH s.ROWID = t.ROWID
CONNECT BY source_id = PRIOR id
AND PRIOR col1 IS NULL
)
) AS col1,
source_id
FROM table_name t;
(результат такой же, как и выше).
db <> fiddle здесь