2014-02-18 3 views
3

Можно ли одновременно получать две разные скользящие средние из одного и того же набора данных MySQL?MySQL: Две скользящие средние в одном запросе?

Я пытаюсь извлечь данные из базы данных MySQL, которая дает мне «сырые» данные плюс две разные скользящие средние одного и того же набора данных. Моя лучшая попытка ниже, проблема в том, что две скользящие средние, по-видимому, дают одинаковые результаты?

Кроме того, существует ли более эффективный способ запроса данных? Набор данных достаточно велик, и этот запрос занимает слишком много времени для запуска?

SELECT 
    t1.`DateTime`, 

    t1.`Positive` AS `RawData`, 

(SELECT AVG(t2.`Positive`) 
FROM `tbl_DATA_KeywordResults` as t2 
WHERE t2.`DateTime` <= t1.`DateTime` 
ORDER BY t2.`DateTime` DESC 
LIMIT 96 
) AS `DailyAverage`, 

(SELECT AVG(t3.`Positive`) 
FROM `tbl_DATA_KeywordResults` as t3 
WHERE t3.`DateTime` <= t1.`DateTime` 
ORDER BY t3.`DateTime` DESC 
LIMIT 674 
) AS `WeeklyAverage` 

FROM `tbl_DATA_KeywordResults` AS t1 
ORDER BY t1.`DateTime`; 
+0

Я не вижу лучшего способа сразу. Какие индексы находятся на вашем столе? – GarethD

+0

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

ответ

1

Вы принимаете предел после вы среднее. Правильная форма подзапроса будет:

(select avg(Positive) 
from (SELECT t2.`Positive` 
     FROM `tbl_DATA_KeywordResults` as t2 
     WHERE t2.`DateTime` <= t1.`DateTime` 
     ORDER BY t2.`DateTime` DESC 
     LIMIT 96 
    ) t 
) AS `DailyAverage` 

я не на 100% уверен, что это будет работать как подзапрос. Я полагаю, что MySQL ограничивает внешние ссылки (что находится в статье where) на один уровень.

Есть более болезненные способы сделать это в MySQL:

select t1.DateTime, t1.RawData, 
     avg(case when t2.DateTime between avg_96_dt and t1.DateTime then t2.Positive end) as avg96, 
     avg(case when t2.DateTime between avg_674_dt and t1.DateTime then t2.Positive end) as avg674 
from (SELECT t1.`DateTime`, t1.`Positive` AS `RawData`, 
      (SELECT t2.DateTime 
       FROM `tbl_DATA_KeywordResults` t2 
       WHERE t2.`DateTime` <= t1.`DateTime` 
       ORDER BY t2.`DateTime` DESC 
       LIMIT 95, 1 
      ) as avg_96_dt, 
      (SELECT t2.DateTime 
       FROM `tbl_DATA_KeywordResults` t2 
       WHERE t2.`DateTime` <= t1.`DateTime` 
       ORDER BY t2.`DateTime` DESC 
       LIMIT 673, 1 
      ) as avg_674_dt 
     FROM `tbl_DATA_KeywordResults` t1 
    ) t1 join 
    tbl_DATA_KeywordResults t2 
group by t1.DateTime, t1.RawData 
ORDER BY t1.`DateTime`; 

То есть, получить лимиты на временной диапазон даты, а затем сделать в среднем на другом этапе.

+0

Спасибо за ответ. Когда я пытаюсь выполнить первый пример, я получаю «Неизвестный столбец» t1.DateTime в ошибке «where clause», которую я не могу исправить? Второй пример возвращает обе скользящие средние как значения NULL для всех периодов? – AdamDynamic

+0

@AdamDynamic. , , Первый запрос - это подзапрос. Его нужно использовать так же, как и ваши подзапросы. Результаты NULL во втором запросе будут исправлены. У меня есть логика «между» в неправильном порядке. –

Смежные вопросы