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 dlaDatekolumna) być najmniejszą możliwą wartością.