34,838
社区成员




--DROP TABLE Monitor
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
*/