Вставка значений в строки NULL на основе ближайшей даты, которая не является NULL и предшествует дате строки - PullRequest
2 голосов
/ 07 мая 2020

Я получаю курсы обмена валют через Riksbanken API. Этот API не дает значений для праздников, субботы или воскресенья. Так что мои курсы валют пока что пусты. Однако, когда я конвертирую валюты в своих таблицах, я выполняю соединение на основе даты и валюты. Итак, в случае, когда у меня транзакция в воскресенье, я не могу ее преобразовать, потому что это NULL, а сумма транзакции * NULL = NULL.

В основном это моя ситуация:

DECLARE @fxrates TABLE(cur varchar(5), rate decimal, rowDate date);
INSERT INTO @fxrates VALUES
 ('EUR',10.40,'2020-04-30')
, ('EUR',10.50,'2020-05-01')
, ('EUR',NULL,'2020-05-02')
, ('EUR',NULL,'2020-05-03')
, ('EUR',10.60,'2020-05-04')
, ('EUR',10.70,'2020-05-05')


DECLARE @value TABLE(cur varchar(5), amount decimal, rowDate date);
INSERT INTO @value VALUES
 ('EUR',1500,'2020-04-30')
, ('EUR',9000,'2020-05-01')
, ('EUR',1000,'2020-05-02')
, ('EUR',300,'2020-05-03')
, ('EUR',160,'2020-05-04')
, ('EUR',170,'2020-05-05')


--How I convert the values
select v.amount * fx.rate as [Converted amount] from @fxrates fx 
JOIN @value v
on fx.cur=v.cur
and fx.rowDate=v.rowDate

Моим решением для этого было бы всегда заменять NULL на «более раннее» значение, основанное на дате. Однако я понятия не имею, как этот logi c будет реализован в SQL. Итак, моя таблица fxrates будет выглядеть так:

 ('EUR',10.40,'2020-04-30')
 ('EUR',10.50,'2020-05-01')
 ('EUR',10.50,'2020-05-02')
 ('EUR',10.50,'2020-05-03')
 ('EUR',10.60,'2020-05-04')
 ('EUR',10.70,'2020-05-05')

Будет ли замена значений NULL лучшим подходом для продвижения вперед? И как я могу этого добиться, используя SQL?

Ответы [ 2 ]

2 голосов
/ 07 мая 2020

Думаю, вы можете использовать CROSS APPLY, чтобы получить последний обменный курс, действующий до или на дату транзакции.

SELECT v.amount * fx.rate AS [Converted amount]
       FROM @value v
            CROSS APPLY (SELECT TOP 1
                                fx.rate
                                FROM @fxrates fx
                                WHERE fx.cur = v.cur
                                      AND fx.rowdate <= v.rowdate
                                      AND fx.rate IS NOT NULL
                                ORDER BY fx.rowdate DESC) fx;
1 голос
/ 07 мая 2020

Здесь можно использовать коррелированный подзапрос, чтобы найти самую последнюю цену, отличную от NULL, для каждой даты, для которой отсутствует цена:

SELECT
    cur,
    COALESCE(rate,
        (SELECT TOP 1 f2.rate FROM @fxrates f2
         WHERE f2.cur = f1.cur AND f2.rowDate < f1.rowDate AND f2.rate IS NOT NULL
         ORDER BY f2.rowdate DESC)
    ) AS rate,
    rowDate
FROM @fxrates f1
ORDER BY
    cur,
    rowDate;

screen capture of demo below

Демо

...