Tsql SQL Server查询以获取连续发生的开始和结束
我有一个包含3列的表,分别是Machine、Time和Status,其中存储了不同系统的信息以及在不同时间捕获的状态Tsql SQL Server查询以获取连续发生的开始和结束,tsql,Tsql,我有一个包含3列的表,分别是Machine、Time和Status,其中存储了不同系统的信息以及在不同时间捕获的状态 Machine Time status ----------------------------------- MAC_1 2016-10-06 06:48 OFF MAC_1 2016-10-06 07:48 OFF MAC_1 2016-10-06 08:48 ON MAC_1 2016-10-06 09:48
Machine Time status
-----------------------------------
MAC_1 2016-10-06 06:48 OFF
MAC_1 2016-10-06 07:48 OFF
MAC_1 2016-10-06 08:48 ON
MAC_1 2016-10-06 09:48 ON
MAC_1 2016-10-06 10:48 ON
MAC_1 2016-10-06 11:48 OFF
MAC_1 2016-10-06 12:48 OFF
MAC_2 2016-10-06 06:48 OFF
MAC_2 2016-10-06 07:48 OFF
MAC_2 2016-10-06 08:48 OFF
MAC_2 2016-10-06 09:48 ON
MAC_2 2016-10-06 10:48 ON
MAC_2 2016-10-06 11:48 OFF
现在,我正试图获得每台机器的连续开关时间窗口
我们正在努力实现的结果如下:
Machine Status StartTime EndTime
-----------------------------------------------------------
MAC_1 OFF 2016-10-06 06:48 2016-10-06 07:48
MAC_1 ON 2016-10-06 08:48 2016-10-06 10:48
MAC_1 OFF 2016-10-06 11:48 2016-10-06 12:48
MAC_2 OFF 2016-10-06 06:48 2016-10-06 08:48
MAC_2 ON 2016-10-06 09:48 2016-10-06 10:48
MAC_2 OFF 2016-10-06 11:48 2016-10-06 11:48
请帮忙
问候,,
RON这是一个典型的数据孤岛问题。如果您有SQL Server 2012或更高版本,则可以使用窗口功能获得所需的结果,如下例所示:
DECLARE @MachineStatus TABLE
(
[Machine] NVARCHAR(50)
,[Time] DATETIME
,[status] NVARCHAR(5)
,PRIMARY KEY([Machine], [Time])
)
INSERT INTO @MachineStatus
(
[Machine]
,[Time]
,[status]
)
VALUES
('MAC_1', '2016-10-06 06:48', 'OFF'),
('MAC_1', '2016-10-06 07:48', 'OFF'),
('MAC_1', '2016-10-06 08:48', 'ON'),
('MAC_1', '2016-10-06 09:48', 'ON'),
('MAC_1', '2016-10-06 10:48', 'ON'),
('MAC_1', '2016-10-06 11:48', 'OFF'),
('MAC_1', '2016-10-06 12:48', 'OFF'),
('MAC_2', '2016-10-06 06:48', 'OFF'),
('MAC_2', '2016-10-06 07:48', 'OFF'),
('MAC_2', '2016-10-06 08:48', 'OFF'),
('MAC_2', '2016-10-06 09:48', 'ON'),
('MAC_2', '2016-10-06 10:48', 'ON'),
('MAC_2', '2016-10-06 11:48', 'OFF');
WITH CTE_MachineStateChange
AS
(
SELECT [Machine]
,[Time]
,[status]
,(
CASE
WHEN LAG([status], 1, '') OVER (PARTITION BY [Machine] ORDER BY [Time]) <> [status] THEN 1
ELSE 0
END
) AS [StateChanged]
FROM @MachineStatus M
), CTE_MachineStateGroupByID
AS
(
SELECT [Machine]
,[Time]
,[status]
,SUM([StateChanged]) OVER (PARTITION BY [Machine] ORDER BY [Time] ROWS UNBOUNDED PRECEDING) AS [GroupByID]
FROM CTE_MachineStateChange
)
SELECT [Machine]
,[status] AS [Status]
,MIN([Time]) AS [StartTime]
,MAX([Time]) AS [EndTime]
FROM CTE_MachineStateGroupByID
GROUP BY [Machine], [GroupByID], [status]
如果您有sql server 2008
create table #test(mac varchar(100), mac_dt datetime, mac_stat varchar(100))
insert into #test values
('MAC_1', '2016-10-06 06:48', 'OFF')
,('MAC_1', '2016-10-06 07:48', 'OFF')
,('MAC_1', '2016-10-06 08:48', 'ON')
,('MAC_1', '2016-10-06 09:48', 'ON')
,('MAC_1', '2016-10-06 10:48', 'ON')
,('MAC_1', '2016-10-06 11:48', 'OFF')
,('MAC_1', '2016-10-06 12:48', 'OFF')
,('MAC_2', '2016-10-06 06:48', 'OFF')
,('MAC_2', '2016-10-06 07:48', 'OFF')
,('MAC_2', '2016-10-06 08:48', 'OFF')
,('MAC_2', '2016-10-06 09:48', 'ON')
,('MAC_2', '2016-10-06 10:48', 'ON')
,('MAC_2', '2016-10-06 11:48', 'OFF');
with cte as
(select mac, mac_dt, mac_stat, row_number() over(order by mac, mac_dt) - row_number() over(order by mac, mac_stat) as grp
from #test)
select t1.mac Machine, t3.mac_stat [Status], t3.StartTime, t3.EndTime
from #test t1 cross apply(select t2.mac, min(mac_dt) as StartTime, max(mac_dt) as EndTime, t2.mac_stat
from cte t2
where t1.mac = t2.mac and t1.mac_stat = t2.mac_stat
group by t2.mac, t2.grp, t2.mac_stat) t3
where t1.mac = t3.mac and t1.mac_stat = t3.mac_stat
and t1.mac_dt = t3.StartTime
order by t1.mac, t3.StartTime
谢谢你,爱德蒙。这个解决方案对我来说非常有效。谢谢你Shishir。这个解决方案也给了我预期的结果。我有一个2012年的实例。因此,我们将采用第一种解决方案。您的解决方案帮助我了解了如果我们有早期版本,该如何做。