0

我有两张桌子:

账单 :

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

汇率:

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。我想返回nearest <= RateDate并获取汇率。是否可以使用同一更新语句中的修改或其他一些有效的方法?(我想避免使用光标)。

4

2 回答 2

1

您应该能够通过子查询来实现这一点。希望我下面的示例可以不加修改地工作(并且没有错误!)唯一需要注意的是您需要用您的报告(基础)货币代替我假设的“美元”。

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 条款

于 2009-03-06T10:05:23.700 回答
0

当然这是可能的 - 作为一个 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任何一天的记录都不会超过一个
  • 有一条FxRate记录早于所有Bill记录

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

另请注意,这是 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
  )
于 2009-03-06T10:03:23.140 回答