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

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

Автор Тема: Создание недельной таблицы с данными температур  (Прочитано 1383 раз)

avtzarenko

  • Новичок
  • *
  • Сообщений: 10
    • Просмотр профиля
Добрый день.
Просьба подсказать  или указать на ветку где уже обсуждалась проблема.
Есть три температурных датчика T_3, T_6, T_7 с переодичностью сохранения данных 30 минут.
Необходимо выводить на форму в таблицу Table5 данные за предыдущую неделю в разрезе данных на 00 и 12 часов.
Каждый понедельник таблица должна пересчитываться. В отчете это работает отлично, а вот на форму проблема, не хватает мозгов.
Начало понятно...
Код
var
  aQuery: string;
  aWeek: TDateTime;
begin
aWeek := StartOfTheWeek(Now);
then begin
  aQuery := 'SELECT 'T_3' as ''Улица'', 'T_6' as ''1 этаж'', 'T_7' as ''2 этаж'' FROM 'my_table';

....

  Table5.RunSQL(aQuery, tsAll);
end.

Во вложении пример как в отчете
« Изменён: 15 Августа 2024, 17:16:36 от Simple_Scada »

pan2000

  • Постоялец
  • ***
  • Сообщений: 188
    • Просмотр профиля
   Здравствуйте.

  Запрос к БД должен содержать фильтры, ограничивающие выборку данных только за одну предыдущую неделю с прореживанием данных.
  Простой фильтры предполагает, что метки времени попадают в первый минутный интервал периода измерения, т.е. минуты = 0 или 30, а секунды = 00..59:
 
Код: (delphi)
var aFirstDay: TDateTime;
begin
  aFirstDay := IncDay(DATE, - (6 + integer(DayOfTheWeek(Now))));                    // первый день пред. недели
  Table5.RunSQL('SELECT DATE_FORMAT(`t`,''%d.%m.%Y  %H:%i'')'                       // форматирование даты-времени
              + ',FORMAT(`T_3`,2),FORMAT(`T_6`,2),FORMAT(`T_7`,2) FROM `my_table` ' // форматирование температур
              + 'WHERE (MINUTE(`t`) = 0) '                                          // фильтр: минуты=0 или начало часа
              + 'AND ((HOUR(`t`) MOD 12) = 0) '                                     // фильтр: час=0 или час=12
              + 'AND (`t` >=' + MySQLDateTime(aFirstDay, dttHour)                   // фильтр: предыдущая неделя - начало
              + ') AND (`t` <' + MySQLDateTime(IncDay(aFirstDay, 7), dttHour)       //         предыдущая неделя - конец
              + ') ;',
              tsSaveFixRow);
end.
Во вложении пример построения исходной таблицы за две предшествующие и начало текущей недели. Построение таблицы результатов.
« Изменён: 17 Августа 2024, 04:52:54 от pan2000 »

avtzarenko

  • Новичок
  • *
  • Сообщений: 10
    • Просмотр профиля
Спасибо Большое!!!
НЕ посмотрел куда создал вопрос и думал, что меня игнорируют и создал вопрос в другой ветке и начал дальше писать но уже через sql
Видимо я неверно описал структуру таблиц.
trends_data - таблица БД
ID - уникальный идентификатор датчика (в запросе участвует 1619,1623,1627)
Value - значение датчика
Timestamp - дата и время записи значения датчика (несколько значений в час) и дабо брать первое значение т.к в час значений два

Немного подправил привязки к моей БД, при компиляции всё ок, при проверке ошибка
Обычный скрипт, привязка к кнопке
В чем может быть ошибка?

Код: (delphi)
var aFirstDay: TDateTime;
begin
  aFirstDay := IncDay(DATE, - (6 + integer(DayOfTheWeek(Now))));                           // первый день пред. недели
  Table5.RunSQL('SELECT FORMAT(`Timestamp`,''%d.%m.%Y  %H:%i'') as Time_1 , trends_data.ID  as ID, trends_data.Value as Value_1  FROM `trends_data` '                              // форматирование даты-времени и добавление фильтра столбцов
              + 'WHERE trends_data.ID in (1619,1623,1627)'
              + 'AND (MINUTE(`Time_1`) = 0) '                                                   // фильтр: минуты=0 или начало часа
              + 'AND ((HOUR(`Time_1`) MOD 12) = 0) '                                            // фильтр: час=0 или час=12
              + 'AND (`Time_1` >=' + MySQLDateTime(aFirstDay, dttHour)                          // фильтр: предыдущая неделя - начало
              + ') AND (`Time_1` <' + MySQLDateTime(IncDay(aFirstDay, 7), dttHour)              //         предыдущая неделя - конец
              + ') ;',
              tsSaveFixRow);
end.

« Изменён: 22 Августа 2024, 15:38:00 от Simple_Scada »

pan2000

  • Постоялец
  • ***
  • Сообщений: 188
    • Просмотр профиля
   Здравствуйте.

  Запрос к БД должен "расыпать" один столбец данных исходной таблицы на три столбца данных, причем с использованием фильтрации по ID данных и по времени.
  На фильтр по времени существнно влияет как формируется временная метка записи в БД, либо от внешней архивируемой переменной, либо от внутренней по временным событиям scada-сервера.
  В примере из вложения фильтр по одиночному значению метки времени в пределах первой минуты часа/получаса. При отсутствии метки времени в пределах фильтрации, выдается сообщение "нет данных". ЛКМ на выбранной ячейке удаляет соответствующую строку тестовой таблицы.
  Предварительно строится временная таблица меток времени от начала недели с интервалом в 12 часов, далее формируется запрос на объединение таблицы меток и трех таблиц данных, полученных подзапросами.
 
  P.S. Иллюзия "игнорирования" - в разделе "Ваши вопросы" обнаружено всего 12 вопросов без ответов :), да и то многие из них предполагают отсутствие ответов. 
« Изменён: 25 Августа 2024, 18:40:07 от pan2000 »

avtzarenko

  • Новичок
  • *
  • Сообщений: 10
    • Просмотр профиля
Спасибо большое.
В итоге вышел из ситуации несколькими таблицами и двумя кнопками, со временем допилю,чтобы сама обновлялась каждую неделю.
Может кому будет полезно.
Описание:
Таблица показаний температурных датчиков за период. Показаний датчика несколько в час, выбрать показания  ночью с 00 до 01 и днём с 12 до 13.
trends_data - основная таблица sql
variables_data - связанная таблица с описанием поля
ID - уникальный идентификатор, он же id переменной
Description - описание переменной (в итоге не понадобилось)
Value - показания
Timestamp - дата-время показаний

Пример заполнения одной таблицы:
Код: (delphi)
var
     aQuery_1:string;
begin
     aQuery_1 :=   'WITH RankedData_1 (Date_1, Value_1, ID_1,   Descr_1, Time_1, Rank_1) AS' // декларируем временную таблицу
                         +'('                                                                                                               // выборка из БД
                         +'SELECT '
                         +' CAST(Timestamp as date) AS Date_1, '                                                       // извлекаем дату
                         +' convert(numeric(10,2), trends_data.Value) as Value_1, '                              // приводим показания к формату два знака после запятой
                         +' trends_data.ID as ID_1, '
                         +'variables_data.Description AS Descr_1, '
                         +' FORMAT(Timestamp ,''HH:mm:ss'') AS Time_1, '                                       // извлекаем время
                         +' ROW_NUMBER() OVER (PARTITION BY CAST (Timestamp as date), trends_data.ID ORDER BY FORMAT(Timestamp ,''HH:mm:ss'')) AS Rank_1 ' // подсчитываем количество показаний в час
                         +' FROM trends_data join variables_data on trends_data.ID = variables_data.ID '  // связываем таблицы
                         +' WHERE trends_data.ID in (1619) AND (FORMAT(Timestamp ,''HH:mm:ss'') BETWEEN ''12:00:00'' AND ''13:00:00'') '  // фильтруем по ID датчика и времени получения показаний
                         +' )'
            +' SELECT  top (30) Date_1, Value_1'                                                           // добавляем в итоговую таблицу необходимые данные - последние 30
            +'   FROM RankedData_1  '
            +'   WHERE Rank_1 = 1  '                                                                            // оставляем первое значение часа
            +'   ORDER BY Date_1 desc, ID_1 desc,  Time_1 desc';

  Table5.RunSQL(aQuery_1, tsSaveFixRow);
 
  Text225.Visible := True;
  Text225.Text := 'Температура днём';
end.                                 
« Изменён: 28 Августа 2024, 10:41:04 от Simple_Scada »