Выполнение интерполяции на столе, группировка по 3-му полю

У меня есть таблица SQL Server 2008+ с тремя столбцами:

Delta (float)
Rate (float)
and Date (datetime)

Мне нужно иметь возможность сгенерировать таблицу тарифов для всех дельт на определенную дату, интерполируя при необходимости. Я могу сделать это хорошо для отдельных значений Delta, но выполнение этого для всех Delta одновременно ставит меня в тупик.

Некоторые примеры данных

Rate    ForwardDate             Delta
1.3528  2013-09-30 00:00:00.000 -0.9
1.3528  2013-09-30 00:00:00.000 -0.75
1.3528  2013-09-30 00:00:00.000 -0.5
1.3528  2013-09-30 00:00:00.000 -0.25
1.3528  2013-09-30 00:00:00.000 -0.1
7.121   2013-10-30 00:00:00.000 -0.9
7.152   2013-10-30 00:00:00.000 -0.75
7.387   2013-10-30 00:00:00.000 -0.5
7.972   2013-10-30 00:00:00.000 -0.25
8.564   2013-10-30 00:00:00.000 -0.1
6.972   2013-12-30 00:00:00.000 -0.9
7.035   2013-12-30 00:00:00.000 -0.75
7.405   2013-12-30 00:00:00.000 -0.5
8.275   2013-12-30 00:00:00.000 -0.25
9.187   2013-12-30 00:00:00.000 -0.1
7.185   2014-03-30 00:00:00.000 -0.9
7.321   2014-03-30 00:00:00.000 -0.75
7.82    2014-03-30 00:00:00.000 -0.5
8.919   2014-03-30 00:00:00.000 -0.25
10.075  2014-03-30 00:00:00.000 -0.1
7.755   2014-09-30 00:00:00.000 -0.9
7.92    2014-09-30 00:00:00.000 -0.75
8.485   2014-09-30 00:00:00.000 -0.5
9.76    2014-09-30 00:00:00.000 -0.25
11.175  2014-09-30 00:00:00.000 -0.1

Лучшее, что я придумал, это:

(
SELECT Delta, ( DATEDIFF(d, @PreviousDate, @ForwardDate) * NextRate 
                   + DATEDIFF(d, @ForwardDate, @NextDate) * PreviousRate
                   ) / DATEDIFF(d, @PreviousDate, @NextDate) AS Rate

FROM 
 (SELECT Main.Delta AS Delta, PR.Rate AS PreviousRate, NR.Rate AS NextRate
  FROM @RatesTable Main
  INNER JOIN @RatesTable PR on PR.Delta = Main.Delta AND PR.ForwardDate = @PreviousDate
  INNER JOIN @RatesTable NR on NR.Delta = Main.Delta AND NR.ForwardDate = @NextDate) AS PrevNextRateTable);

куда @NextDate а также @PreviousDate взяты из более раннего расчета, чтобы определить даты в таблице, ближайшей к дате теста (@ForwardDate). Это необходимо, так как мы должны убедиться, что все интерполяции находятся между одними и теми же двумя датами (давая NULL, если в одну из дат отсутствует одно значение). Я не хочу интерполировать между разными датами для каждого значения дельты.

Это дает мне то, что кажется перекрестным соединением результатов

Delta   Rate
-0.9    7.742609
-0.75   7.906979
-0.5    8.470543
-0.25   9.741717
-0.1    11.15109
-0.9    7.742609
-0.75   7.906979
-0.5    8.470543
-0.25   9.741717
-0.1    11.15109
-0.9    7.742609
-0.75   7.906979
-0.5    8.470543
-0.25   9.741717
-0.1    11.15109
-0.9    7.742609
-0.75   7.906979
-0.5    8.470543
-0.25   9.741717
-0.1    11.15109
-0.9    7.742609
-0.75   7.906979
-0.5    8.470543
-0.25   9.741717
-0.1    11.15109

с 5 результатами для каждой дельты. Я могу SELECT DISTINCT это при необходимости, но не могу не думать, что это обман, и я делаю что-то не так. Есть ли лучший способ, который устраняет необходимость SELECT DISTINCT?

1 ответ

Решение

Попробуй это:

SELECT Delta, ( DATEDIFF(d, @PreviousDate, @ForwardDate) * NextRate 
                   + DATEDIFF(d, @ForwardDate, @NextDate) * PreviousRate
                   ) / DATEDIFF(d, @PreviousDate, @NextDate) AS Rate

FROM 
 (SELECT Main.Delta AS Delta, PR.Rate AS PreviousRate, NR.Rate AS NextRate
  FROM @RatesTable Main
  INNER JOIN @RatesTable PR on PR.Delta = Main.Delta AND PR.ForwardDate = @PreviousDate
  INNER JOIN @RatesTable NR on NR.Delta = Main.Delta AND NR.ForwardDate = @NextDate) AS PrevNextRateTable
GROUP BY Delta,
        ( DATEDIFF (d, @PreviousDate, @ForwardDate) * NextRate 
                   + DATEDIFF(d, @ForwardDate, @NextDate) * PreviousRate
                   ) / DATEDIFF(d, @PreviousDate, @NextDate) ;
Другие вопросы по тегам