2016-08-11 7 views
-1

Я использую MySql и есть данные в следующем формате:Moving Average в MySql

Date  | Product | Value 
----------------------------- 
2016-01-01 | ProA | 121.30 
2016-01-02 | ProA | 122.50 
2016-01-03 | ProA | 120.75 
2016-01-06 | ProA | 125.33 
2016-01-10 | ProA | 119.85 
----------------------------- 

Мое требование является запрос для получения выходного сигнала в формате с всех столбцов в таблице выше наряду с скользящая средняя для «n» дней. Он должен запрашивать большие данные. Выход может быть в следующем формате, если «п» 3:

Date  | Product | Value | MovingAvg 
----------------------------------------- 
2016-01-01 | ProA | 121.30 | 
2016-01-02 | ProA | 122.50 | 
2016-01-03 | ProA | 120.75 | 121.52 
2016-01-06 | ProA | 125.33 | 122.86 
2016-01-10 | ProA | 119.85 | 121.98 
----------------------------------------- 

Этот запрос для использования в моем Приложеиние в VB.net Заранее спасибо за помощь

+0

ли скользящую среднюю исправить? Пожалуйста, дважды проверьте ожидаемый результат – 1000111

+0

@ 1000111. Результат правильный, первый 121,52 - это номер 121.30, 1222.50, 120.75 и т. Д. Для других также – Kris

+0

Не могли бы вы объяснить вывод? Вы не рассчитываете ** Совокупная скользящая средняя **? – 1000111

ответ

2

Вот одна идея. Обратите внимание, что решение, налагающее переменные, будет на порядок быстрее ...

В наборе результатов выборки отсутствуют средние значения, содержащие менее 3 значений, но я оставлю это как упражнение для читателя ... (хотя я ' ве включал зацепка)

SELECT a.date 
    , a.product 
    , a.value 
    , ROUND(AVG(b.value),2) rolling 
    FROM 
    (SELECT x.* 
      , COUNT(*) rank 
     FROM my_table x 
     JOIN my_table y 
      ON y.product = x.product 
      AND y.date <= x.date 
     GROUP 
      BY x.product 
      , x.date 
    ) a 
    LEFT 
    JOIN 
    (SELECT x.* 
      , COUNT(*) rank 
     FROM my_table x 
     JOIN my_table y 
      ON y.product = x.product 
      AND y.date <= x.date 
     GROUP 
      BY x.product 
      , x.date 
    ) b 
    ON b.product = a.product 
    AND b.rank BETWEEN a.rank - 2 AND a.rank 
GROUP 
    BY a.date,a.product; 
+0

это замечательно. Однако я сделал небольшую настройку, чтобы сделать ее идеальной. – Kris

+0

Не выбрано ли значение «значение», так как оно не является частью группы? –

+1

@KamilG. технически да - но я группируюсь по мощности 1, поэтому он должен всегда возвращать правильное значение. MySQL прощает такое поведение (хотя это спорно ли оно должно быть). Вы можете добавить значение в GROUP BY, если хотите, или работаете в строгом режиме. – Strawberry

0
select a.date 
    , a.product 
    , a.value 
    , round(avg(b.value),2) rolling 
from 
    (
    select x.* 
     , count(*) rank 
     from my_table x 

     join my_table y 

     on y.product=x.product 

     and y.date >=x.date 

     group 
     by x.product, 
     x.date order by x.date asc 
    ) 
a 


left 
join 

     (select x.*, 
     count(*) rank 
     from my_table x 

     join my_table y 

     on y.product = x.product 

     and y.date >= x.date 

     group 
     by x.product 
     , x.date order by x.date asc 
    ) 
    b 

    on b.product =a.product 

    and a.rank between b.rank -2 and b.rank 

group 
    by a.date, a.product order by a.date desc; 
Смежные вопросы