Расчет скользящего среднего с использованием mysql приводит к проблемам, если в наборах данных есть пробелы - PullRequest
0 голосов
/ 12 ноября 2018

Моя проблема в том, что я пытаюсь вычислить скользящее среднее по некоторым значениям из моей таблицы (по одному среднему значению для каждой строки). Это на самом деле работает, но если дело доходит до пробелов, таких как id [20,18,17] или date [2018-05-11,2018-05-9,2018-05-8] расчет становится неправильным. Я ищу способ использовать определенное количество следующих строк, чтобы этого не произошло.

Таблица содержит id (auto_increment), date and close (Float).

Это мой код:

CREATE DEFINER=`root`@`localhost` PROCEDURE `moving_avg`(IN periode INT)
    NO SQL
BEGIN
    select hist_ask.id, hist_ask.date, hist_ask.close, round(avg(past.close),2) as mavg   
    from hist_ask    
    join hist_ask as past     
      on past.id between hist_ask.id - (periode-1)  and hist_ask.id
    group by hist_ask.id, hist_ask.close 
    ORDER BY hist_ask.id DESC 
    LIMIT 10;
END

Таблица, которую я использую, выглядит следующим образом

id , date       , close
20 , 2018-10-13 , 12086.5
19 , 2018-10-12 , 12002.2
17 , 2018-10-11 , 12007.0
and so on

Вывод выглядит так:

Вывод, полученный по запросу

Заранее спасибо!

1 Ответ

0 голосов
/ 21 ноября 2018

Я наконец заставляю его работать, используя временную таблицу. Теперь я могу дать два параметра для процедуры:

  1. Период: период скользящее среднее рассчитывается с
  2. _limit: ограничивает набор результатов

Важным для производительности является

ALTER TABLE temp
    ENGINE=MyISAM;

оператор, поскольку он значительно сокращает время выполнения. Например, для обработки 2000 строк требуется около 0,5 секунды, а для добавления нужно около 6 секунд

Вот код:

CREATE DEFINER=`root`@`localhost` PROCEDURE `moving_avg`(IN periode INT, IN _limit INT)
    NO SQL
BEGIN

 DECLARE a FLOAT DEFAULT 0;
 DECLARE i INT DEFAULT 0;
 DECLARE count_limit INT  DEFAULT 0;

   SET @rn=0;
 CREATE TEMPORARY TABLE IF NOT EXISTS temp (
                SELECT 
                    @rn:=@rn+1 AS pri_id, 
                    date, 
                    close , a AS 
                    mavg 
                FROM hist_ask);

ALTER TABLE temp
ENGINE=MyISAM;

 SET i=(SELECT pri_id FROM temp ORDER by pri_id DESC LIMIT 1);
 SET count_limit= (i-_limit)-periode;


WHILE i>count_limit DO
SET a= (SELECT avg(close) FROM temp WHERE pri_id BETWEEN i-(periode-1) AND i);
UPDATE temp SET mavg=a WHERE pri_id=i;
SET i=i-1;
END WHILE;

SELECT pri_id,date,close,round(mavg,2) AS mavg FROM temp ORDER BY pri_id DESC LIMIT _limit;


DROP TABLE temp;

END

Результат выглядит так:

CALL `moving_avg`(3,5)
  • pri_id, дата, закрытие, mavg
  • 1999 2018-09-13 12086,6 12032,03
  • 1998 2018-09-11 12002.2 11983.47
  • 1997 2018-09-10 12007,3 11976,53
  • 1996 2018-09-07 11940,9 11993.80
  • 1995 2018-09-06 11981,4 12089,23

5 строк возвращено 0,047 с / 0,000 с

...