Добрый день!
Стоит задача сделать отчёт из архивных данных таблицы trends_data. Туда пишут показания счётчики, необходимо построить отчёт за период, выбрав показания на начало интервала, на конец интервала и разницу за интервал (расход) в рамках периода. С отчётом из стандартного источника всё понятно, задаём переменные начала, конца и интервала и добавляем архивные теги с нужной выборкой, всё красиво. НО, появилась необходимость сделать отчёт гибко настраиваемый пользователем, в котором заранее неизвестно сколько переменных будет использоваться - может 1, а может 25. И их можно постоянно менять из интерфейса программы. Тут уже стандартный источник не подходит, т.к. даже если задать динамическую адресацию, количество переменных фиксированное и просто будет оставаться куча пустых строк. Создавать десятки отчётов на все возможные варианты тоже не решение, поэтому было решено использовать источник MySQL и запрос:
SELECT round(MIN(value),2) AS minVal, round(MAX(value),2) AS maxVal,
round(MAX(value),2) - round(MIN(value),2) AS aEnergy
FROM trends_data
WHERE id IN(
SELECT idvar FROM areas WHERE idarea = @area
)
&& timestamp BETWEEN @tstart AND @tend
&& quality = 1
GROUP BY id
В запросе получаем значение на начало периода, конец периода и разницу значений. ID переменных получаем вложенным запросом из своей таблицы (в ней то и будет пользователь выбирать нужные ему счётчики). Отчёт строится, например за час, но как сделать отчёт за сутки с разбивкой на заданные интервалы (например час)? Понимаю что нужно вычислить для каждого интервала какое-то общее значение времени в рамках часа например и группировать по нему. Но как реализовать пока непонятно, жду ваших предложений.
При фиксированных значениях границ интервала (например, на начало каждого часа) можно использовать постоянную таблицу, данные в которую добавляются каждый час.
В таблице trends_data у меня содержатся и архивные данные записанные из скады, и данные которые я туда пишу скриптами каждые полчаса с фиксированной меткой времени 00, 30 минут.
Я немного модифицировал запрос, чтобы сгруппировать данные по часам - разделил метки времени переведенные в число на 3600 и оставил целую часть. Получились часы, но туда входят данные до 59:59, а следующее значение записано в 00:00 и в нужный интервал не попадает.
SELECT round(MIN(value),2) AS minVal, round(MAX(value),2) AS maxVal,
round(MAX(value),2) - round(MIN(value),2) AS aEnergy,
timestamp,
floor(time_to_sec(timestamp)/3600) as period
FROM trends_data
WHERE id IN(
SELECT idvar FROM areas WHERE idarea = @area
)
&& timestamp BETWEEN @tstart AND @tend
&& quality = 1
GROUP BY id, period
В отчете созданном из стандартного источника всё хорошо, с запросом беда :'(
Можно попробовать выполнять несколько выборок и затем объединять их в одну. Вот пример объединения двух простых выборок:
(
select * from `trends_data`
where (`id`=1) and (`timestamp` = '2021-11-14 12:50:02.325')
) UNION (
select * from `trends_data`
where (`id`=1) and (`timestamp` = '2021-11-14 12:50:06.335')
)
Какого-то простого решения для данной задачи мы не видим. Лучше всего было бы решить её используя стандартные источники, но для этой задачи они не предусмотрены и непонятно как можно было бы их улучшить, чтобы они подходили для решения (и при этом оставались простыми в настройке).