0

私は2つのテーブルを持っています:

明細書 :

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為替レートを取得したいのですが、同じ update ステートメントまたは他の効率的な方法で変更を行うことは可能ですか? (カーソルを避けたい)。

4

2 に答える 2

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 に答える