【问题标题】:Inserting values to NULL rows based on the closest date that is not NULL and is earlier than the row date根据非 NULL 且早于行日期的最接近日期将值插入 NULL 行
【发布时间】:2020-05-07 10:10:04
【问题描述】:

我从 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 替换为“较早”的值。但是我不知道如何在 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 来实现?

【问题讨论】:

  • 更重要的是 - 将列声明为十进制是一个问题。如果不指定精度和小数位数,您的列将使用默认值 decimal(18,0)。它不能存储像 10.4 这样的数字。

标签: sql-server tsql date insert


【解决方案1】:

我认为您可以使用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;

【讨论】:

  • 不错!此解决方案与其他解决方案略有不同,但实际上更好地满足了我的目的,因为在某些情况下,我的表格中没有所有日期。不幸的是,我已经接受了另一个答案,因为它确实解决了我所要求的问题。感谢您的帮助,但这是最适合我的解决方案!
【解决方案2】:

您可以在此处使用相关子查询来查找缺少价格的每个日期的最新非 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;

Demo

【讨论】:

  • @Anton 可能有一种方法可以使用分析函数来做到这一点,这可能会少一些代码。不确定性能,在所有情况下,都必须进行反向查找才能找到最接近的非 NULL 速率。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-11
  • 2019-03-29
  • 1970-01-01
  • 2021-02-21
  • 1970-01-01
相关资源
最近更新 更多