当值丢失时更新数据库表

发布于 2024-07-14 05:20:40 字数 886 浏览 8 评论 0原文

我有两个表:

Bill:

create table Bill(
               BillDate datetime,
               Amount decimal(10,2) ,
               BillCurrency varchar(3) ,
               ReportingCurrency decimal(10,2))

FxRate:

create table FxRate( 
               RateDate datetime,
               SourceCurrency varchar(3),
               TargetCurrency varchar(3),
               ExchangeRate decimal(15,4))

这就是我想要做的:

我想更新我的 Bill 表,因为

update Bill 
set ReportingCurrency = FxRate.ExchangeRate * Bill.Amount
from FxRate
where FxRate.RateDate = Bill.BillDate

在此更新所有包含以下条目的行:该特定日期将获得新的报告货币数据。 由于 Bill 表可以有多行符合更新条件,因此我遇到以下问题:

对于 FxRate 表(该日期)中没有条目的行,ReportingCurrency 变为 NULL。 我想返回最近的 <= RateDate 并获取汇率。是否可以使用同一更新语句中的修改或其他一些有效的方法? (我想避免光标)。

I have two tables :

Bill :

create table Bill(
               BillDate datetime,
               Amount decimal(10,2) ,
               BillCurrency varchar(3) ,
               ReportingCurrency decimal(10,2))

FxRate :

create table FxRate( 
               RateDate datetime,
               SourceCurrency varchar(3),
               TargetCurrency varchar(3),
               ExchangeRate decimal(15,4))

This is what I want to do :

I want to update my Bill table as

update Bill 
set ReportingCurrency = FxRate.ExchangeRate * Bill.Amount
from FxRate
where FxRate.RateDate = Bill.BillDate

In this update all the rows which have an entry for that particular date will get the new reportingcurrency data. Since Bill table can have multiple rows eligible for the update , I have the following problem :

For the rows where there was no entry in FxRate table (for that date), the ReportingCurrency becomes NULL. I want to go back to the nearest <= RateDate and pick up the exchange rate.Is that possible using modifications in the same update statement or some other efficient method? (I want to avoid a cursor).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笔芯 2024-07-21 05:20:40

您应该能够通过子查询来实现这一点。 希望我下面的示例无需修改即可运行(并且不会出现错误!)唯一的注意事项是您需要用您的报告(基础)货币替换我假设的“美元”。

UPDATE Bill SET ReportingCurrency = (Bill.Amount * 
  (SELECT TOP 1 FxRate.ExchangeRate FROM FxRate
   WHERE FxRate.SourceCurrency = Bill.BillCurrency
   AND FxRate.TargetCurrency = 'USD'
   AND FxRate.RateDate <= Bill.BillDate
   ORDER BY FxRate.RateDate DESC))

希望这可以帮助。 编辑 - 添加 ORDER BY 子句

You should be able to achieve this with a subquery. Hopefully my example below will work unmodified (and be error free!) The only note is you need to substitute your reporting (base) currency for my assumed 'USD'.

UPDATE Bill SET ReportingCurrency = (Bill.Amount * 
  (SELECT TOP 1 FxRate.ExchangeRate FROM FxRate
   WHERE FxRate.SourceCurrency = Bill.BillCurrency
   AND FxRate.TargetCurrency = 'USD'
   AND FxRate.RateDate <= Bill.BillDate
   ORDER BY FxRate.RateDate DESC))

Hope this helps. EDIT - Added ORDER BY Clause

云柯 2024-07-21 05:20:40

当然这是可能的 - 作为 SELECT,这将是:

SELECT
  b.BillDate,
  r.RateDate,
  r.ExchangeRate
FROM
  Bill b
  LEFT JOIN FxRate r ON r.RateDate = (
    SELECT MAX(RateDate) FROM FxRate WHERE RateDate <= b.BillDate
  )

因此,作为更新:

UPDATE
  Bill
SET
  ReportingCurrency = r.ExchangeRate * b.Amount
FROM
  Bill b
  LEFT JOIN FxRate r ON r.RateDate = (
    SELECT MAX(RateDate) FROM FxRate WHERE RateDate <= b.BillDate
  )

解决方案做出以下假设:

  • 对于任何给定的一天,永远不会有超过一个 FxRate 记录,
  • 有一个 早于所有 Bill 记录的 FxRate 记录

如果这些假设不适用,则必须适应查询。

另请注意,这是 SQL Server 语法。 Sybase 可能有点不同。


由于评论者对一般的“最近日期”解决方案表现出兴趣:

UPDATE
  Bill
SET
  ReportingCurrency = r.ExchangeRate * b.Amount
FROM
  Bill b
  LEFT JOIN FxRate r ON r.RateDate = (
    SELECT TOP 1 RateDate 
    FROM         FxRate
    ORDER BY     ABS(DATEDIFF(d, RateDate, b.BillDate)), RateDate
  )

不过,这会很慢。 选择:

UPDATE
  Bill
SET
  ReportingCurrency = CASE 
                      WHEN DATEDIFF(d, r1.RateDate, b.BillDate) <= DATEDIFF(d, b.BillDate, r2.RateDate)
                      THEN r1.ExchangeRate
                      ELSE COALESCE(r2.ExchangeRate, r1.ExchangeRate)
                      END * b.Amount
FROM
  Bill b
  LEFT JOIN FxRate r1 ON r1.RateDate = (
    SELECT MAX(RateDate) FROM FxRate WHERE RateDate <= b.BillDate
  )
  LEFT JOIN FxRate r2 ON r2.RateDate = (
    SELECT MIN(RateDate) FROM FxRate WHERE RateDate >= b.BillDate
  )

Of course this is possible - as a SELECT this would be:

SELECT
  b.BillDate,
  r.RateDate,
  r.ExchangeRate
FROM
  Bill b
  LEFT JOIN FxRate r ON r.RateDate = (
    SELECT MAX(RateDate) FROM FxRate WHERE RateDate <= b.BillDate
  )

Therefore, as an UPDATE:

UPDATE
  Bill
SET
  ReportingCurrency = r.ExchangeRate * b.Amount
FROM
  Bill b
  LEFT JOIN FxRate r ON r.RateDate = (
    SELECT MAX(RateDate) FROM FxRate WHERE RateDate <= b.BillDate
  )

The solution makes these assumptions:

  • there is never more than one FxRate record for any given day
  • there is an FxRate record that predates all Bill records

If these assumptions are not applicable, the query must be accommodated.

Also note that this is SQL Server syntax. It's possible that Sybase is a little different.


Since a commenter showed interest in a general "nearest date" solution:

UPDATE
  Bill
SET
  ReportingCurrency = r.ExchangeRate * b.Amount
FROM
  Bill b
  LEFT JOIN FxRate r ON r.RateDate = (
    SELECT TOP 1 RateDate 
    FROM         FxRate
    ORDER BY     ABS(DATEDIFF(d, RateDate, b.BillDate)), RateDate
  )

This would be quite slow, though. Alternative:

UPDATE
  Bill
SET
  ReportingCurrency = CASE 
                      WHEN DATEDIFF(d, r1.RateDate, b.BillDate) <= DATEDIFF(d, b.BillDate, r2.RateDate)
                      THEN r1.ExchangeRate
                      ELSE COALESCE(r2.ExchangeRate, r1.ExchangeRate)
                      END * b.Amount
FROM
  Bill b
  LEFT JOIN FxRate r1 ON r1.RateDate = (
    SELECT MAX(RateDate) FROM FxRate WHERE RateDate <= b.BillDate
  )
  LEFT JOIN FxRate r2 ON r2.RateDate = (
    SELECT MIN(RateDate) FROM FxRate WHERE RateDate >= b.BillDate
  )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文