Primero puede hacer una autounión en los tipos de cambio que están ordenados por fecha para que tenga la fecha de inicio y finalización de cada tipo de cambio, sin superposición o brecha en las fechas (tal vez agregue eso como vista a su base de datos - en mi caso, solo estoy usando una expresión de tabla común).
Ahora unir esas tarifas "preparadas" con las transacciones es simple y eficiente.
Algo como:
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)
Notas:
-
Podrías reemplazar
GETDATE()
con una fecha en un futuro lejano, asumo aquí que no se conocen tarifas para el futuro. -
La regla (B) se implementa estableciendo la fecha del primer tipo de cambio conocido en la fecha mínima admitida por SQL Server
datetime
, que debería (por definición, si es el tipo que está usando para laDate
columna) sea el valor más pequeño posible.