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 laDatecolumna) sea el valor más pequeño posible.