Можете първо да направите самообединяване на обменните курсове, които са подредени по дата, така че да имате началната и крайната дата на всеки обменен курс, без никакво припокриване или пропуск в датите (може би добавете това като изглед към вашата база данни - в моя случай просто използвам общ израз на таблица).
Сега свързването на тези „подготвени“ курсове с транзакциите е лесно и ефективно.
Нещо като:
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)
Бележки:
-
Можете да замените
GETDATE()
с дата в далечното бъдеще, тук предполагам, че не са известни курсове за бъдещето. -
Правило (B) се прилага чрез задаване на датата на първия известен обменен курс на минималната дата, поддържана от SQL Server
datetime
, което трябва (по дефиниция, ако е типът, който използвате заDate
колона) бъде възможно най-малката стойност.