SQL Server查询以获得持续发生

时间:2016-11-30 11:41:48

标签: sql sql-server

最近我遇到了一个要求,我有源表,

Machine_Name|    Time             |   Alarm 
------------|---------------------|---------
Mac1        |    2016-11-22 05:15 |   0     
Mac1        |    2016-11-22 05:30 |   1     
Mac1        |    2016-11-22 05:45 |   1     
Mac1        |    2016-11-22 06:00 |   0     
Mac1        |    2016-11-22 06:15 |   1     
Mac1        |    2016-11-22 06:30 |   1     
Mac1        |    2016-11-22 06:45 |   1     
Mac1        |    2016-11-22 07:00 |   1     
Mac1        |    2016-11-22 07:15 |   1     
Mac1        |    2016-11-22 07:30 |   1     
Mac2        |    2016-11-22 05:15 |   0     
Mac2        |    2016-11-22 05:30 |   0     
Mac2        |    2016-11-22 05:45 |   1     
Mac2        |    2016-11-22 06:00 |   1     
Mac2        |    2016-11-22 06:15 |   1     
Mac2        |    2016-11-22 06:30 |   1     
Mac2        |    2016-11-22 06:45 |   0     
Mac2        |    2016-11-22 07:00 |   1     

上表列出了设施中安装的差异化机器的详细信息及其发布警报'每个时期的状态(每15分钟一次)。

现在我需要计算此警报的相关性。对于任何单个警报,相关性为25%。如果机器连续4个时间(1小时)发出警报,则将最大相关性归档100%。

如果警报连续超过4个(1小时),则相关性保持不变100%。

上述源表的预期结果集如下,

Machine_Name|    Time             |   Alarm |  Alert_Relevancy(%)
------------|---------------------|---------|---------------
Mac1        |    2016-11-22 05:15 |   0     |  0 
Mac1        |    2016-11-22 05:30 |   1     |  25 
Mac1        |    2016-11-22 05:45 |   1     |  50 
Mac1        |    2016-11-22 06:00 |   0     |  0 
Mac1        |    2016-11-22 06:15 |   1     |  25 
Mac1        |    2016-11-22 06:30 |   1     |  50 
Mac1        |    2016-11-22 06:45 |   1     |  75 
Mac1        |    2016-11-22 07:00 |   1     |  100 
Mac1        |    2016-11-22 07:15 |   1     |  100
Mac1        |    2016-11-22 07:30 |   1     |  100
Mac2        |    2016-11-22 05:15 |   0     |  0 
Mac2        |    2016-11-22 05:30 |   0     |  0 
Mac2        |    2016-11-22 05:45 |   1     |  25 
Mac2        |    2016-11-22 06:00 |   1     |  50 
Mac2        |    2016-11-22 06:15 |   1     |  75 
Mac2        |    2016-11-22 06:30 |   1     |  100 
Mac2        |    2016-11-22 06:45 |   0     |  0 
Mac2        |    2016-11-22 07:00 |   1     |  25 

如果我还可以获得一个查询来选择那些连续引发至少4次的警报系列(相关性达到100),那将会很棒。

预期的第二个结果集如下,我已经删除了连续至少4次不是1的任何警报系列。

Machine_Name|    Time             |   Alarm |  Alert_Relevancy(%)
------------|---------------------|---------|---------------
Mac1        |    2016-11-22 06:15 |   1     |  25 
Mac1        |    2016-11-22 06:30 |   1     |  50 
Mac1        |    2016-11-22 06:45 |   1     |  75 
Mac1        |    2016-11-22 07:00 |   1     |  100 
Mac1        |    2016-11-22 07:15 |   1     |  100
Mac1        |    2016-11-22 07:30 |   1     |  100
Mac2        |    2016-11-22 05:45 |   1     |  25 
Mac2        |    2016-11-22 06:00 |   1     |  50 
Mac2        |    2016-11-22 06:15 |   1     |  75 
Mac2        |    2016-11-22 06:30 |   1     |  100 

提前感谢您的建议/查询示例。

此致 RON

2 个答案:

答案 0 :(得分:2)

select      Machine_Name
           ,time
           ,Alarm
           ,case when alarm_seq >= 4 then 4 else alarm_seq end * 25

from       (select      *
                       ,sum (Alarm) over 
                        (
                            partition by    Machine_Name,group_id 
                            order by        time
                        )                           as alarm_seq

            from       (select      *
                                   ,count (nullif(alarm,1)) over 
                                    (
                                        partition by    Machine_Name 
                                        order by        time
                                    )   as group_id

                        from        t
                        ) t
            ) t
select      Machine_Name
           ,time
           ,Alarm
           ,case when alarm_seq >= 4 then 4 else alarm_seq end * 25

from       (select      *
                       ,sum (Alarm) over 
                        (
                            partition by    Machine_Name,group_id 
                            order by        time
                        )                           as alarm_seq

                       ,sum (Alarm) over 
                        (
                            partition by    Machine_Name,group_id 
                        )                           as alarms

            from       (select      *
                                   ,count (nullif(alarm,1)) over 
                                    (
                                        partition by    Machine_Name 
                                        order by        time
                                    )   as group_id

                        from        t
                        ) t
            ) t

where       alarms >= 4
        and alarm = 1

答案 1 :(得分:1)

使用带有row_number和递归CTE的CTE

SQL使用表变量进行演示。

declare @SourceTable table (Machine_Name varchar(4), [Time] datetime, Alarm bit);

insert into @SourceTable values
('Mac1','2016-11-22 05:15',0),
('Mac1','2016-11-22 05:30',1),
('Mac1','2016-11-22 05:45',1),
('Mac1','2016-11-22 06:00',0),
('Mac1','2016-11-22 06:15',1),
('Mac1','2016-11-22 06:30',1),
('Mac1','2016-11-22 06:45',1),
('Mac1','2016-11-22 07:00',1),
('Mac1','2016-11-22 07:15',1),
('Mac1','2016-11-22 07:30',1),
('Mac2','2016-11-22 05:15',0),
('Mac2','2016-11-22 05:30',0),
('Mac2','2016-11-22 05:45',1),
('Mac2','2016-11-22 06:00',1),
('Mac2','2016-11-22 06:15',1),
('Mac2','2016-11-22 06:30',1),
('Mac2','2016-11-22 06:45',0),
('Mac2','2016-11-22 07:00',1);

;with CTE as
(
   select
   row_number() over (partition by Machine_Name order by [Time]) as rn,
   Machine_Name, [Time], Alarm
   from @SourceTable
),
RECURSIVE_CTE as 
(
   select Machine_Name, [Time], Alarm, rn, rn as rn_root, 0 as Relevancy
   from CTE
   where Alarm = 0
   UNION ALL
   select CTE.Machine_Name, CTE.[Time], CTE.Alarm, CTE.rn, R.rn_root, case when R.Relevancy = 100 then 100 else (R.Relevancy + 25) end
   from RECURSIVE_CTE R 
   JOIN CTE ON (R.Machine_Name = CTE.Machine_Name AND R.rn + 1 = CTE.rn AND CTE.Alarm = 1)
)
select R.Machine_Name, R.[Time], R.Alarm, R.Relevancy as [Alert_Relevancy(%)]
from RECURSIVE_CTE R
INNER JOIN (select Machine_Name, rn_root from RECURSIVE_CTE where Relevancy = 100 group by Machine_Name, rn_root) M
ON (R.Machine_Name = M.Machine_Name and R.rn_root = M.rn_root)
where R.Relevancy > 0
order by R.Machine_Name, R.[Time];

返回:

Mac1    2016-11-22 06:15:00.000 1   25
Mac1    2016-11-22 06:30:00.000 1   50
Mac1    2016-11-22 06:45:00.000 1   75
Mac1    2016-11-22 07:00:00.000 1   100
Mac1    2016-11-22 07:15:00.000 1   100
Mac1    2016-11-22 07:30:00.000 1   100
Mac2    2016-11-22 05:45:00.000 1   25
Mac2    2016-11-22 06:00:00.000 1   50
Mac2    2016-11-22 06:15:00.000 1   75
Mac2    2016-11-22 06:30:00.000 1   100