Я предположил, что есть только 2 валюты, но, кажется, их может быть больше. Поэтому я обновил свой запрос для обработки всех валют. Вот мой пример таблицы:
create or replace table currencies (ctimestamp varchar, ctype varchar,
fcurr varchar, tcurr varchar, conv_ration number(3,2) )
as select * from values
('20200101' , 'M' , 'EUR' , 'USD' , 0.9),
('20200201' , 'M' , 'EUR' , 'USD' , 0.85),
('20200229' , 'C' , 'INR' , 'EUR' , 0.4);
Вот мое решение, которое не использует никаких временных таблиц или хранимых процедур, а просто SQL:
with generated_days as
(select to_varchar( dateadd( days, row_number() over (order by 1) - 1, (select min(to_date(ctimestamp,'YYYYMMDD')) from currencies)), 'YYYYMMDD' ) gtimestamp
from table(generator(rowcount => 10000))
),
first_last_days as
(select gtimestamp, IFF(substring(gtimestamp, -2 ) = '01', 'M', 'C' ) mc
from generated_days where ( substring(gtimestamp, -2 ) = '01' or last_day( to_date(gtimestamp,'YYYYMMDD')) = to_date(gtimestamp,'YYYYMMDD'))
and to_date(gtimestamp,'YYYYMMDD') <= current_date
),
curtypes as
(select ctype || fcurr || tcurr pkey, ctype, max(ctimestamp) max_date from currencies group by ctype || fcurr || tcurr, ctype),
combination as (
select pkey, gtimestamp, null ctype, null fcurr, null tcurr, null conv_ration
from first_last_days
join curtypes on gtimestamp > max_date and ctype = mc
union all
select ctype || fcurr || tcurr pkey, * from currencies
order by pkey, gtimestamp)
select
gtimestamp, left( pkey, 1 ) ctype,
NVL(fcurr, lag( fcurr, 1, NULL ) ignore nulls over (partition by pkey order by gtimestamp )) fcurr,
NVL(tcurr, lag( tcurr, 1, NULL ) ignore nulls over (partition by pkey order by gtimestamp )) tcurr,
NVL(conv_ration, lag( conv_ration, 1, NULL ) ignore nulls over (partition by pkey order by gtimestamp)) conv_ration
from combination
order by ctype, fcurr, tcurr, gtimestamp;
Сначала я генерирую даты, затем выберите только первый и последний дни каждого месяца. Я группирую существующие данные по каждой валюте и типу. Я присоединяюсь к этим группам с доступными датами и объединяюсь с существующими значениями. Я заполняю пропущенные значения с помощью функции LAG.
Вот результат вышеприведенного запроса:
+------------+-------+-------+-------+-------------+
| GTIMESTAMP | CTYPE | FCURR | TCURR | CONV_RATION |
+------------+-------+-------+-------+-------------+
| 20200229 | C | INR | EUR | 0.40 |
| 20200331 | C | INR | EUR | 0.40 |
| 20200101 | M | EUR | USD | 0.90 |
| 20200201 | M | EUR | USD | 0.85 |
| 20200301 | M | EUR | USD | 0.85 |
| 20200401 | M | EUR | USD | 0.85 |
+------------+-------+-------+-------+-------------+