所以,我有一张表,上面有这样的行:
Ev_Message Ev_Comment EV_Custom1 Ev_Time_Ms ------------------------------------------------------------------------------------- Machine 1 Alarm 5/23/2016 11:02:00 AM Alarms Scanned 25 Machine 1 Alarm 5/23/2016 11:00:00 AM Alarms Scanned 686 Machine 1 Alarm 5/23/2016 11:00:00 AM Light curtain 537 Machine 1 Alarm 5/23/2016 11:00:00 AM Guard door open 346 Machine 1 Alarm 5/23/2016 11:00:00 AM No control voltage 135 Machine 1 Alarm 5/23/2016 10:38:34 AM Alarms Scanned 269 Machine 1 Alarm 5/23/2016 10:38:29 AM Alarms Scanned 378 Machine 1 Alarm 5/23/2016 10:38:29 AM Guard door open 156 Machine 1 Alarm 5/23/2016 10:38:25 AM Alarms Scanned 654 Not an Alarm 5/23/2016 10:38:25 AM Not an Alarm 467 Machine 1 Alarm 5/23/2016 10:38:25 AM Guard door open 234 Machine 1 Alarm 5/23/2016 10:38:25 AM No control voltage 67 Machine 1 Alarm 5/23/2016 10:38:23 AM Alarms Scanned 124 Machine 1 Alarm 5/23/2016 10:38:23 AM No control voltage 100
每次扫描警报时(即每次触发或清除警报时)都会添加“已扫描的警报”行。任何警报都会添加带有特定Ev_Custom1的行。第一列Ev_Message包含一个计算机ID,该ID使我可以将警报与其他计算机分开。(您不喜欢任意的列名吗?)超过900条独特的警报消息。
我希望查询返回的内容是这样的:
Alarm Message Alarm Start Time Alarm Stop Time ---------------------------------------------------------------- No control voltage 5/23/2016 10:38:23 AM 5/23/2016 10:38:29 AM Guard door open 5/23/2016 10:38:25 AM 5/23/2016 10:38:34 AM No control voltage 5/23/2016 11:00:00 AM 5/23/2016 11:02:00 AM Guard door open 5/23/2016 11:00:00 AM 5/23/2016 11:02:00 AM Light curtain 5/23/2016 11:00:00 AM 5/23/2016 11:02:00 AM
这将是两个日期之间过滤的查询。我可以更改进入表的数据,但是有900个警报,我的自由度受到限制。
在一些帮助下,我当前的查询是这样的:
WITH T AS ( SELECT s.Ev_Comment AS start_time, MIN(COALESCE (e.Ev_Comment, s.Ev_Comment)) AS end_time FROM A AS s INNER JOIN A AS e ON s.Ev_Comment < e.Ev_Comment AND s.Ev_Custom1 = 'Alarms Scanned' AND e.Ev_Custom1 = 'Alarms Scanned' GROUP BY s.Ev_Comment) SELECT T_1.start_time, T_1.end_time, A.Ev_Custom1 FROM A INNER JOIN T AS T_1 ON A.Ev_Comment LIKE T_1.start_time WHERE (A.Ev_Custom1 <> 'Alarms Scanned')
我仍然有一个问题。如果警报持续的时间超过一个时间,例如“警卫门打开”的时间从10:38:25到10:38:34,则它将以两行显示,如下所示:
start_time end_time EV_Custom1 --------------------- --------------------- ------------- 5/23/2016 10:38:25 AM 5/23/2016 10:38:29 AM Guard door open 5/23/2016 10:38:29 AM 5/23/2016 10:38:34 AM Guard door open
理想情况下,我想要的是:
start_time end_time EV_Custom1 --------------------- --------------------- ------------- 5/23/2016 10:38:25 AM 5/23/2016 10:38:34 AM Guard door open
我想我需要group by ((Ev_custom1) and (when end_time = start_time)) (请原谅我的伪代码),但我对此所需的语法了解不足。
group by ((Ev_custom1) and (when end_time = start_time))
这是一个SQLFiddle
如果我正确理解发布的问题,那么您的CTE会有效地确定所有警报的时间段(或时间间隔)。您的最终select子句将实际的警报信息与您的警报间隔结合在一起。问题的一部分是,如果您的警报长时间处于活动状态(我假设比您的警报扫描周期长),那么警报系统将继续记录“扫描的警报”条目,这实际上会导致划分活动警报。如果您具有SQL Server 2012或更高版本,则比较容易确定警报事件是否被拆分。您只需要检查警报的结束时间是否等于相同警报类型的下一个警报的开始时间。您可以在2012年使用LAG窗口功能来实现这一目标。 下一步是生成一个ID,您可以对警报进行分组,以便可以合并拆分事件。这是通过SUM OVER子句实现的。以下示例显示了如何实现此目的:
;WITH AlarmTimeBuckets AS ( SELECT EventStart.Ev_Comment AS StartDateTime ,MIN(COALESCE (EventEnd.Ev_Comment, EventStart.Ev_Comment)) AS EndDateTime ,EventStart.Ev_Message As Machine FROM A EventStart INNER JOIN A EventEnd ON EventStart.Ev_Comment < EventEnd.Ev_Comment AND EventStart.Ev_Custom1 = 'Alarms Scanned' AND EventEnd.Ev_Custom1 = 'Alarms Scanned' AND EventStart.Ev_Message = EventEnd.Ev_Message GROUP BY EventStart.Ev_Message, EventStart.Ev_Comment ), AlarmsByTimeBucket AS ( SELECT AlarmTimeBuckets.Machine ,AlarmTimeBuckets.StartDateTime ,AlarmTimeBuckets.EndDateTime ,Alarm.Ev_Custom1 AS Alarm ,( CASE WHEN LAG(AlarmTimeBuckets.EndDateTime, 1, NULL) OVER (PARTITION BY Alarm.Ev_Custom1,Alarm.Ev_Message ORDER BY AlarmTimeBuckets.StartDateTime) = AlarmTimeBuckets.StartDateTime THEN 0 ELSE 1 END ) AS IsNewEvent FROM A Alarm INNER JOIN AlarmTimeBuckets ON Alarm.Ev_Message = AlarmTimeBuckets.Machine AND Alarm.Ev_Comment = AlarmTimeBuckets.StartDateTime WHERE (Alarm.Ev_Custom1 <> 'Alarms Scanned') ) , AlarmsByGroupingID AS ( SELECT Machine ,StartDateTime ,EndDateTime ,Alarm ,SUM(IsNewEvent) OVER (ORDER BY Machine, Alarm, StartDateTime) AS GroupingID FROM AlarmsByTimeBucket ) SELECT MAX(Machine) AS Machine ,MIN(StartDateTime) AS StartDateTime ,MAX(EndDateTime) AS EndDateTime ,MAX(Alarm) AS Alarm FROM AlarmsByGroupingID GROUP BY GroupingID ORDER BY StartDateTime