2012-04-12 5 views
2

Я хочу создать отчет о временной шкале, который показывает, для каждой даты на временной шкале перемещение среднее из последних N точек данных в наборе данных, которое имеет некоторые меры и даты, которые они измеряли. У меня есть таблица календаря, заполненная каждый день, чтобы указать даты. Я могу рассчитать график, чтобы показать общий среднего до этой даты довольно просто с корреляцией подзапросом (реальная ситуация гораздо сложнее, чем это, но она по существу может быть упрощена до этого):Как вычислить скользящее среднее в MySQL в коррелированном подзапросе?

SELECT c.date 
,  ( SELECT AVERAGE(m.value) 
      FROM measures as m 
      WHERE m.measured_on_dt <= c.date 
     ) as `average_to_date` 
FROM calendar c 
WHERE c.date between date1 AND date2 -- graph boundaries 
ORDER BY c.date ASC 

Я читал об этом несколько дней, и я не нашел хороших решений. Некоторые предположили, что LIMIT может работать в подзапросе (LIMIT поддерживается в подзапросах текущей версии MySQL), однако LIMIT применяется к набору возвращаемых значений, а не к строкам, входящим в совокупность, поэтому не имеет значения, добавить их.

Я также могу написать неагрегированный SELECT с LIMIT и затем скомпилировать его, потому что коррелированный подзапрос не допускается внутри оператора FROM. Так что это (к сожалению) не будет работать:

SELECT c.date 
,  SELECT AVERAGE(last_5.value) 
     FROM ( SELECT m.value 
       FROM measures as m 
       WHERE m.measured_on_dt <= c.date 
       ORDER BY m.measured_on_dt DESC 
       LIMIT 5 
      ) as `last_5` 
FROM calendar c 
WHERE c.date between date1 AND date2 -- graph boundaries 
ORDER BY c.date ASC 

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

UPDATE: Хорошо, у меня есть решение, которое я упростил для этого примера. Он полагается на некоторую обманчивость пользовательской переменной, чтобы количественно измерять показатели с календарной даты. Он также выполняет кросс-продукт с таблицей календаря (вместо подзапроса), но у этого есть неудачный побочный эффект, связанный с тем, что трюк с нумерацией строк терпит неудачу (пользовательские переменные оцениваются, когда они отправляются клиенту, а не когда строка оценивается), поэтому для обхода этого я должен был вложить запрос на один уровень, заказать результаты, а затем применить трюк нумерации строк к этому набору, который затем работает.

Этот запрос возвращает только даты календаря, для которых существуют меры, поэтому, если вы хотите, чтобы вся временная шкала вы просто выбирали календарь и LEFT JOIN для этого набора результатов.

set @day = 0; 
set @num = 0; 
set @LIMIT = 5; 

SELECT date 
,  AVG(value) as recent_N_AVG 
FROM 
( SELECT * 
    ,  @num := if(@day = c.date, @num + 1, 1) as day_row_number 
    ,  @day := day as dummy 
    FROM 
    (SELECT c.full_date 
    ,  m.value 
    ,  m.measured_on_dt 
    FROM calendar c 
    JOIN measures as m 
    WHERE m.measured_on_dt <= c.full_date 
    AND  c.full_date BETWEEN date1 AND date2 
    ORDER BY c.full_date ASC, measured_on_dt DESC 
) as full_data 
) as numbered 
WHERE day_row_number <= @LIMIT 
GROUP BY date 

Строка нумерация трюк может быть обобщен на более сложные данные (мои меры в нескольких измерениях, которые нуждаются в агрегировании вверх).

+0

Итак, ваше решение саморешено, или вы все еще застряли на чем-то, и если да, то что это такое. Предоставление некоторых выборочных данных тоже помогло бы ... – DRapp

+0

Я разрешил это, но это взломать. Это должна быть общая проблема, поэтому мне интересно, есть ли лучшее решение. – Gruff

+0

На самом деле это не хак, если вам нужно определенное количество на каждую кандидатуру. переменные sql идеально подходят для такого типа обработки. – DRapp

ответ

0

Если ваш график является непрерывным (1 значение каждый день) вы могли бы улучшить свою первую попытку, как это:

SELECT c.date, 
     (SELECT AVERAGE(m.value) 
     FROM measures as m 
     WHERE m.measured_on_dt 
        BETWEEN DATE_SUB(c.date, INTERVAL 5 day) AND c.date 
     ) as `average_to_date` 
FROM calendar c 
WHERE c.date between date1 AND date2 -- graph boundaries 
ORDER BY c.date ASC 

Если ваш график имеет отверстия в ней это привело бы менее 5 значений среднего.

+0

Нет, к сожалению, измеренные данные стохастичны, поэтому это не сработает. – Gruff

+0

@Gruff О, хорошо, я подумаю о вашей новой информации ... – dgw

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

  • Нет связанных вопросов^_^