Генерация оповещения, когда значения датчика и температуры превышают пороговое значение в течение минуты - PullRequest
0 голосов
/ 01 марта 2020

Рассмотрим таблицу с 3 столбцами:

  1. Timestamp: формат hh:mm:ss, который записывается в таблицу каждую секунду
  2. PSI: значение записанного датчика в таблице за каждую секунду
  3. Temp: значение температуры, записанное в таблице каждую секунду

Я хочу написать запрос, который будет генерировать предупреждение, когда

  • если PSI больше 60 и Temp больше 255 в течение более 60 секунд или более непрерывно

Например, если значение PSI > 60 and Temp > 255 от 01:01:15 до 01:02:17 должно быть сгенерировано предупреждение.

Я пытался использовать курсор, чтобы получить эту работу, но запрос работает неправильно. Может кто-нибудь помочь с существующим запросом? Кроме того, может ли кто-нибудь предложить альтернативный и простой запрос к этой формулировке проблемы?

Запрос, который я пробовал:

declare @Timestamp time, @PSI int, @Temp int, @final_timestmp time, @status int 
set @final_timestmp='01:00:00'

declare cr_alert cursor for
    select Timestamp, PSI, Temp
    from [dbo].[Sensor_Values]
    where PSI > 60 and Temp > 255
    order by Timestamp

open cr_alert;

Fetch next from cr_alert into @Timestamp, @PSI, @Temp

while @@FETCH_STATUS = 0
begin
    set @status = 0
    print @status

    if (@Timestamp <> @final_timestmp)
    begin
        set @status = datediff(second, @final_timestmp, @Timestamp)

        if (@status = 1)
        begin
            set @final_timestmp = @Timestamp;

            insert into final_Sensor_Values 
                select @final_timestmp, @PSI, @Temp

            fetch next from cr_alert into @Timestamp, @PSI, @Temp
        end
    end
end

close cr_alert;
deallocate cr_alert;

Пример набора данных:

Timestamp   PSI Temp
01:01:01    59  264
01:01:02    63  247
01:01:03    56  245
01:01:04    64  262
01:01:05    50  245
01:01:06    57  244
01:01:07    64  251
01:01:08    60  259
01:01:09    52  244
01:01:10    52  242
01:01:11    63  259
01:01:12    56  241
01:01:13    51  252
01:01:14    52  261
01:01:15    50  265
01:01:16    54  251
01:01:17    59  243
01:01:18    64  240
01:01:19    55  265

ИЛИ вы можете просмотреть набор данных ниже URL.

https://i.stack.imgur.com/SGJlq.png

Ответы [ 2 ]

0 голосов
/ 01 марта 2020

Если у вас есть одна строка на каждую секунду, вы можете использовать оконные функции:

select sv.*,
       (case when min(temp) over (order by timestamp rows between 59 preceding and current row) > 255 and
                  min(PSI) over (order by timestamp rows between 59 preceding and current row) > 60
             then 'Alert!!!'
        end) as alert                  
from [dbo].[Sensor_Values] sv;

Если секунд может не хватить, вы можете использовать:

with sv as (
      select sv.*, row_number() over (order by timestamp) as seqnum
      from [dbo].[Sensor_Values] sv
     )
select sv.*,
       (case when min(temp) over (order by seqnum range between 59 preceding and current row) > 255 and
                  min(PSI) over (order by seqnum range between 59 preceding and current row) > 60
             then 'Alert!!!'
        end) as alert                  
from [dbo].[Sensor_Values] sv;

Единственное предупреждение здесь является то, что это может генерировать ненужные предупреждения в начале данных.

0 голосов
/ 01 марта 2020
declare @t table
(
Timestamp time,
PSI smallint,
Temp smallint,
index clidx clustered(Timestamp)
--id int identity,
--primary key clustered(Timestamp, id)
);


insert into @t(Timestamp, PSI, Temp)
values
('01:01:01', 59, 264),
('01:01:02', 63, 247),
('01:01:03', 56, 245),
('01:01:04', 64, 262),
('01:01:05', 50, 245),
('01:01:06', 57, 244),
('01:01:07', 64, 251),
('01:01:08', 60, 259),
('01:01:09', 52, 244),
('01:01:10', 52, 242),
('01:01:11', 63, 259),
('01:01:12', 56, 241),
('01:01:13', 51, 252),
('01:01:14', 52, 261),
('01:01:15', 50, 265),
('01:01:16', 54, 251),
('01:01:17', 59, 243),
('01:01:18', 64, 240),
('01:01:19', 55, 265);

select *, case when l.totalrows = 5 and l.minPSI > 50 and l.minTemp > 240 then 1 else 0 end as AlertYN
from @t as t
cross apply
(
    select min(p.PSI) as minPSI, max(p.PSI) as maxPSI, min(p.Temp) as minTemp, max(p.Temp) as maxTemp, count(*) as totalrows
    from @t as p 
    where p.TimeStamp > dateadd(second, -5, t.TimeStamp) --check for last 5 secs
      and p.TimeStamp <= t.TimeStamp
) as l
--where l.minPSI > 50 and l.minTemp > 240
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...