У меня есть таблица базы данных, похожая на следующую:
id | macaddr | load | timestamp
=========================================
1 | 0011111 | 17 | 2012-02-07 10:00:00
1 | 0011111 | 6 | 2012-02-07 12:00:00
2 | 0022222 | 3 | 2012-02-07 12:00:03
3 | 0033333 | 9 | 2012-02-07 12:00:04
4 | 0022222 | 4 | 2012-02-07 12:00:06
5 | 0033333 | 8 | 2012-02-07 12:00:10
...
Теперь я хотел бы рассчитать среднюю нагрузку по всем устройствам (= mac-адресам) за разные периоды времени, например, на сегодня, вчера, на этой неделе, в этом месяце.
Среднюю нагрузку можно рассчитать, сначала определив общую сумму нагрузки в разные моменты времени (даты выборки), а затем рассчитав среднее значение сумм нагрузки для этих дат выборки. Например, если бы я хотел получить среднюю загрузку за последние десять секунд (а сейчас 2012-02-07 12:00:10), я мог бы принять решение о датах выборки в 12:00:02, 12:00: 04, 12:00:06, 12:00:08 и 12:00:10. Затем я вычислил бы суммы нагрузки, суммируя самые последние значения нагрузки для каждого устройства:
2012-02-07 12:00:02 | 6 [= load(id=2)]
2012-02-07 12:00:04 | 18 [= load(id=2) + load(id=3) + load(id=4)]
2012-02-07 12:00:06 | 19 [= load(id=2) + load(id=4) + load(id=5)]
2012-02-07 12:00:08 | 19 [= load(id=2) + load(id=4) + load(id=5)]
2012-02-07 12:00:10 | 18 [= load(id=2) + load(id=5) + load(id=6)]
Значение загрузки устройства игнорируется, если оно старше, например, час (здесь произошло с id = 1). Среднее значение будет 16 в этом случае.
В настоящее время я генерирую довольно сложный запрос со многими операторами «UNION ALL», который очень медленно работает:
SELECT avg(l.load_sum) as avg_load
FROM (
SELECT sum(so.load) AS load_sum
FROM (
SELECT *
FROM (
SELECT si.macaddr, si.load
FROM sensor_data si WHERE si.timestamp > '2012-02-07 11:00:10' AND si.timestamp < '2012-02-07 12:00:10'
ORDER BY si.timestamp DESC
) AS sm
GROUP BY macaddr
) so
UNION ALL
[THE SAME THING AGAIN WITH OTHER TIMESTAMPS]
UNION ALL
[AND AGAIN]
UNION ALL
[AND AGAIN]
...
) l
А теперь представьте, что я хотел бы рассчитать среднюю нагрузку за целый месяц. С почасовыми выборками дат мне нужно объединить 30x24 = 720 запросов, используя оператор UNION ALL Полный запрос занимает около минуты на моем компьютере. Я уверен, что есть гораздо лучшее решение без заявления UNION ALL. Тем не менее, я не нашел ничего полезного в Интернете. Поэтому я был бы очень благодарен за вашу помощь!