大家好,我有一张实时监控设备停机状况的表,其中记录了:
设备编码、设备停机开始时间、设备停机结束时间(若该设备当前正停机,则结束时间为NULL)、停机时长(若该设备当前正停机,则结束时间为NULL)。
由于某些原因,监控设备会把停机记录写成多条记录,即一次停机如果被写成了3条记录,则第1条记录的停机结束是第2条的停机开始;第2条记录的停机结束是第3条记录的停机开始...
现在我需要一个查询,能够查出一个视图,该视图将每个设备多条连续的停机记录合并成一条,请问这个查询怎么写?
正如上图的两种情况,应该分别是:
NO.29 ECOFORCE 2HT3 2013-07-22 16:38:01.000 2013-07-23 22:00:00.000 1760NO.29 ECOFORCE 2HT3 2013-07-25 06:45:00.000 NULL NULLSQL疑难高分
设备编码、设备停机开始时间、设备停机结束时间(若该设备当前正停机,则结束时间为NULL)、停机时长(若该设备当前正停机,则结束时间为NULL)。
由于某些原因,监控设备会把停机记录写成多条记录,即一次停机如果被写成了3条记录,则第1条记录的停机结束是第2条的停机开始;第2条记录的停机结束是第3条记录的停机开始...
现在我需要一个查询,能够查出一个视图,该视图将每个设备多条连续的停机记录合并成一条,请问这个查询怎么写?
正如上图的两种情况,应该分别是:
NO.29 ECOFORCE 2HT3 2013-07-22 16:38:01.000 2013-07-23 22:00:00.000 1760NO.29 ECOFORCE 2HT3 2013-07-25 06:45:00.000 NULL NULLSQL疑难高分
CREATE TABLE Monitor
(
DownTime_id INT,
machine_name VARCHAR(100),
Start_Time DATETIME,
End_Time DATETIME,
Duration DECIMAL(10, 2)
)
INSERT Monitor
SELECT 1, 'a', '2013-01-01 1:00:00', '2013-01-01 2:00:00', 60 UNION ALL
SELECT 2, 'a', '2013-01-01 2:00:00', '2013-01-01 3:00:00', 60 UNION ALL
SELECT 3, 'a', '2013-01-01 3:00:00', NULL, NULL UNION ALL
SELECT 4, 'a', '2013-01-01 8:00:00', '2013-01-01 9:00:00', 60 UNION ALL
SELECT 5, 'a', '2013-01-01 9:00:00', '2013-01-01 10:00:00', 60 UNION ALL
SELECT 6, 'b', '2013-01-01 1:00:00', '2013-01-01 2:00:00', 60--功能是实现了,但效率可能不好。期待更好的算法
--索引1: machine_name, Start_Time
--索引1: machine_name, End_Time
--其它: 根据视图外部的条件,建立合适的索引;WITH cte AS --#1.先找出连续的最后那条记录
(
SELECT *, flag = 1
FROM Monitor A
WHERE NOT EXISTS
(
SELECT 1
FROM Monitor B
WHERE B.machine_name = A.machine_name
AND B.Start_Time = A.End_Time
)
),
cte1 AS --#2.根据最后一条记录递归出所有的连续记录,并将它们放到一个组中(以Downtime_id分组)
(
SELECT * FROM cte
UNION ALL
SELECT a.Downtime_id, b.machine_name, b.Start_Time, b.End_time, b.Duration, flag = 0
FROM cte1 a
INNER JOIN Monitor b
ON a.machine_name = b.machine_name
AND a.Start_Time = b.End_Time
)
SELECT
a.Downtime_id,
a.machine_name,
Start_Time = (SELECT MIN(Start_Time) FROM cte1 b WHERE b.DownTime_id = a.DownTime_id), --#3.把最后这条记录的Start_Time替换成最小的
a.End_time,
a.Duration
FROM cte a/*
Downtime_id machine_name Start_Time End_time Duration
3 a 2013-01-01 01:00:00.000 NULL NULL
5 a 2013-01-01 08:00:00.000 2013-01-01 10:00:00.000 60.00
6 b 2013-01-01 01:00:00.000 2013-01-01 02:00:00.000 60.00
*/