Możesz najpierw wykonać samodzielne dołączenie do kursów wymiany, które są uporządkowane według daty, aby mieć datę rozpoczęcia i zakończenia każdego kursu wymiany, bez nakładania się lub luki w datach (możesz dodać to jako widok do swojej bazy danych - w moim przypadku używam zwykłego wyrażenia tabelowego).
Teraz łączenie tych „przygotowanych” stawek z transakcjami jest proste i wydajne.
Coś takiego:
WITH IndexedExchangeRates AS (
SELECT Row_Number() OVER (ORDER BY Date) ix,
Date,
Rate
FROM ExchangeRates
),
RangedExchangeRates AS (
SELECT CASE WHEN IER.ix=1 THEN CAST('1753-01-01' AS datetime)
ELSE IER.Date
END DateFrom,
COALESCE(IER2.Date, GETDATE()) DateTo,
IER.Rate
FROM IndexedExchangeRates IER
LEFT JOIN IndexedExchangeRates IER2
ON IER.ix = IER2.ix-1
)
SELECT T.Date,
T.Amount,
RER.Rate,
T.Amount/RER.Rate ConvertedAmount
FROM Transactions T
LEFT JOIN RangedExchangeRates RER
ON (T.Date > RER.DateFrom) AND (T.Date <= RER.DateTo)
Uwagi:
-
Możesz zastąpić
GETDATE()
z datą w odległej przyszłości, zakładam, że nie są znane żadne stawki na przyszłość. -
Reguła (B) jest implementowana przez ustawienie daty pierwszego znanego kursu wymiany na minimalną datę obsługiwaną przez SQL Server
datetime
, co powinno (z definicji, jeśli jest to typ, którego używasz dlaDate
kolumna) być najmniejszą możliwą wartością.