SQL oracle пересчет сумм в неотрицательные
У меня есть договор и даты с суммами начислений.
Начисления могут быть с плюсом и минусом, например:
contract_id = 1
01.01.2024 100₽
02.01.2024 500₽
03.01.2024 300₽
04.01.2024 -700₽
05.01.2024 -50₽
06.01.2024 50₽
07.01.2024 -30₽
08.01.2024 100₽
Мне нужно написать sql запрос select, который рассчитает результат таким образом, чтобы вместо отрицательных значений в списке начислений уменьшились ближайшие предыдущие положительные значения, чтобы все значения начислений были неотрицательными, как будто не было отрицательных начислений, а положительные были меньше, то есть:
contract_id = 1
01.01.2024 100₽
02.01.2024 50₽
03.01.2024 0₽
04.01.2024 0₽
05.01.2024 0₽
06.01.2024 20₽
07.01.2024 0₽
08.01.2024 100₽
Каким запросом это можно сделать?
Ответы (1 шт):
Автор решения: ESkri
→ Ссылка
Сначала вычисляете нарастающий итог, потом ищете в нём "будущий минимум":
Подготовка таблицы
create table sums (contract_id number, dt date, amount number);
insert into sums (contract_id, dt, amount)
select 1 as contract_id, date'2024-01-01' as dt, 100 as amount from dual union all
select 1 as contract_id, date'2024-01-02' as dt, 500 as amount from dual union all
select 1 as contract_id, date'2024-01-03' as dt, 300 as amount from dual union all
select 1 as contract_id, date'2024-01-04' as dt, -700 as amount from dual union all
select 1 as contract_id, date'2024-01-05' as dt, -50 as amount from dual union all
select 1 as contract_id, date'2024-01-06' as dt, 50 as amount from dual union all
select 1 as contract_id, date'2024-01-07' as dt, -30 as amount from dual union all
select 1 as contract_id, date'2024-01-08' as dt, 100 as amount from dual;
Запрос
select
contract_id,
dt,
amount,
greatest(0, min(acc) over (partition by contract_id order by dt desc) - acc + amount)
as positive_amount
from
(
select
contract_id,
dt,
amount,
sum(amount) over (partition by contract_id order by dt) as acc
from
sums
)
order by
contract_id,
dt
| CONTRACT_ID | DT | AMOUNT | POSITIVE_AMOUNT |
|---|---|---|---|
| 1 | 01.01.2024 | 100 | 100 |
| 1 | 02.01.2024 | 500 | 50 |
| 1 | 03.01.2024 | 300 | 0 |
| 1 | 04.01.2024 | -700 | 0 |
| 1 | 05.01.2024 | -50 | 0 |
| 1 | 06.01.2024 | 50 | 20 |
| 1 | 07.01.2024 | -30 | 0 |
| 1 | 08.01.2024 | 100 | 100 |