Комплексный минимум скользящих значений - PullRequest
0 голосов
/ 18 февраля 2020

Я работаю над сложной статистической функцией, которая требует нахождения как минимум 10 предыдущих вычисленных значений. Вычисленные значения для каждой из предыдущих строк зависят не только от среднего значения по текущей строке, но также и по вычислениям предыдущих строк. На приведенном ниже рисунке показан желаемый результат запроса:

Illustration

Я могу получить среднее значение за 10 дней, но не могу понять, как применить другие вычисления без использования оконной функции для каждого отдельного сценария, который был бы очень неэффективным. Ниже приведен код, который у меня есть:

CREATE TABLE #TBL(
[id]    int IDENTITY(1,1) NOT NULL,
[price] numeric(20,10)
)

INSERT INTO #TBL ([price])
VALUES (93.02),(90.56),(88.63),(90.3),(91.58),(90.42),(89.5),(89.23),(87.07),(85.88),(86.04),(87.26),(87.67),(84.37),(84.13),(83.3),(82.4),(81.73),(82),(80.69),(82.13)


SELECT
    [id], [price],
    CASE WHEN [id] >= 10 THEN
    avg([price]) OVER(ORDER BY ID ASC ROWS BETWEEN 9 PRECEDING AND CURRENT ROW)
    END  AS [average (last 10)]
FROM #TBL 

Любая помощь в создании эффективного запроса будет принята с благодарностью.

1 Ответ

1 голос
/ 19 февраля 2020
CREATE TABLE #TBL(
[id]    int IDENTITY(1,1) NOT NULL primary key clustered, --!!!!
[price] numeric(20,10)
)

INSERT INTO #TBL ([price])
VALUES (93.02),(90.56),(88.63),(90.3),(91.58),(90.42),(89.5),(89.23),(87.07),(85.88),(86.04),(87.26),(87.67),(84.37),(84.13),(83.3),(82.4),(81.73),(82),(80.69),(82.13)

select *
from
(
  select *, avg([price]) OVER(ORDER BY ID ASC ROWS BETWEEN 9 PRECEDING AND CURRENT ROW) as avg10
  from #TBL 
) as a
outer apply
(

   select min(r.runningdiff) as mindiff
   from
   (
      select sum(l10.diff) over (order by l10.id) as runningdiff
      from
      (
        select TOP (10) b.id, a.avg10 - b.price as diff
        from #Tbl as b
        where 1=1
        and a.Id >= 10
        and b.Id between a.id-9 and a.Id
      ) as l10
   ) as r
) as rt
...