Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Не получили письмо с кодом активации?

Официальный форум Simple-Scada.

Автор Тема: Выборка значений из БД через union  (Прочитано 353 раз)

SergeyP

  • Новичок
  • *
  • Сообщений: 1
    • Просмотр профиля
Выборка значений из БД через union
« : 10 Сентября 2024, 15:09:59 »
Добрый день.
Имеется база данных трендов с значениями датчиков. Требуется выбрать минимальное, максимально и среднее значение из базы по нескольким датчикам и группе датчиков за заданный период времени.

Если делать выборку одним простым запрсом SELECT - проблем нет, данные все получаю, передаю в отчет. Код вот такой:

Код: (delphi)
var

  aQuery: string;               // сам запрос
  aFromStr, aToStr: string;     // интервал времени в виде строки

begin

 aFromStr := MySQLDateTime(DATA_BEGIN.VALUE, dttFull);
 aToStr   := MySQLDateTime(DATA_END.VALUE, dttFull);

   aQuery := 'SELECT TRUNCATE(MIN(`V`), 2), TRUNCATE(MAX(`V`), 2), TRUNCATE(AVG(`V`), 2) ' +
              'FROM `trends` ' +
              'WHERE (`t` >= ' + aFromStr + ') AND (`t` <= ' + aToStr + ') AND ' +
              '((`id` = 21) or (`id` = 23) or (`id` = 25))';
 
RunSQL(aQuery, nil, 1);

end.

Для получения данных по нескольким датчикам использую UNION. Код вот такой тогда использую:

Код: (delphi)
var

  aQuery: string;               // сам запрос
  aFromStr, aToStr: string;     // интервал времени в виде строки

begin

 aFromStr := MySQLDateTime(DATA_BEGIN.VALUE, dttFull);
 aToStr   := MySQLDateTime(DATA_END.VALUE, dttFull);

   aQuery := 'SELECT TRUNCATE(MIN(`V`), 2), TRUNCATE(MAX(`V`), 2), TRUNCATE(AVG(`V`), 2) ' +
              'FROM `trends` ' +
              'WHERE (`t` >= ' + aFromStr + ') AND (`t` <= ' + aToStr + ') AND ' +
              '((`id` = 21) or (`id` = 23) or (`id` = 25))'  +
              'union' +
              'SELECT TRUNCATE(MIN(`V`), 2), TRUNCATE(MAX(`V`), 2), TRUNCATE(AVG(`V`), 2) ' +
              'FROM `trends` ' +
              'WHERE (`t` >= ' + aFromStr + ') AND (`t` <= ' + aToStr + ') AND ' +
              '(`id` = 11)' +
              'union' +
              'SELECT TRUNCATE(MIN(`V`), 2), TRUNCATE(MAX(`V`), 2), TRUNCATE(AVG(`V`), 2) ' +
              'FROM `trends` ' +
              'WHERE (`t` >= ' + aFromStr + ') AND (`t` <= ' + aToStr + ') AND ' +
              '(`id` = 10);';

  RunSQL(aQuery, nil, 1);

end.

Для обработки данных использую скрипт "Выполнен SQL запрос". Вот такой

 
Код: (delphi)
var

 aReport: TM_Report;

begin

  if DataSet.IsEmpty then Exit;
 
  if DataSet.Tag = 1 then
  begin
    MIN_room1.Value := DataSet.Fields[0].AsStr;
    MAX_room1.Value := DataSet.Fields[1].AsStr;
    AVG_room1.Value := DataSet.Fields[2].AsStr;
    MIN_T_room1.Value := DataSet.Fields[3].AsStr;
    MAX_T_room1.Value := DataSet.Fields[4].AsStr;
    AVG_T_room1.Value := DataSet.Fields[5].AsStr;
    MIN_HE_room1.Value := DataSet.Fields[6].AsStr;
    MAX_HE_room1.Value := DataSet.Fields[7].AsStr;
    AVG_HE_room1.Value := DataSet.Fields[8].AsStr;
    end;

  aReport := ReportBuild('Камера газации 1');
  aReport.View(GetClientName);
                                           
end.

Для простой выборки через SELECT - все работает.  При применении UNION - не работает.

Подскажите, к в чем может быть проблема с запросом к базе? Или как реализовать по нажатию кнопки выполнение нескольких запросов с последующей передачей данных в переменные и отчет.


« Изменён: 10 Сентября 2024, 15:42:59 от Simple_Scada »

Simple_Scada

  • Администратор
  • *****
  • Сообщений: 1247
    • Просмотр профиля
Re: Выборка значений из БД через union
« Ответ #1 : 12 Сентября 2024, 12:59:30 »
Здравствуйте.

Цитировать
Требуется выбрать минимальное, максимально и среднее значение из базы по нескольким датчикам и группе датчиков за заданный период времени. ...как реализовать по нажатию кнопки выполнение нескольких запросов с последующей передачей данных в переменные и отчет.
Если указанные данные нужны для построения отчета, то для решения задачи не требуется использовать скрипты и SQL-запросы.

Вы можете создать периодический отчет и на шаге добавления переменной в источник выбрать соответствующий "тип обработки" -> "минимум", "максимум" или "среднее". Далее переменной интервала "Данные_Интервал" нужно задать значение равное 0, тогда вычисления будут производиться за весь период времени, без разбивки на интервалы. Теперь полученные переменные можно перетащить на страницу отчета (см. скриншот во вложении). В итоге, при построении отчета в эти переменные будет выводиться минимум, максимум и среднее за необходимый промежуток времени. Перед вызовом построения отчета нужно задать требуемый интервал времени через соответствующие переменные - в примере это переменные "vrTimeBegin" и "vrTimeEnd".

Дополнительные рекомендации:
1. При формировании SQL-запросов к штатной БД необходимо указывать нужный слой архива для выборки - см. описание колонки "l". Это позволит исключить лишние данные. В Вашем случае, можно было использовать основной слой.
2. Данные, полученные через приведенные SQL-запросы могут быть некорректными, особенно это касается вычисления среднего. Через SQL-запрос Вы получите среднее арифметическое точек архива за указанный интервал времени. Данный результат точно будет неправильным, т.к. для корректного вычисления среднего по архивным данным, необходимо учитывать длительность нахождения переменной в каждом значении. Поэтому в отчетах используется вычисление средневзвешенного по времени значения.