Tsql SQL Server查询以获取连续发生的开始和结束

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

我有一个包含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    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年的实例。因此,我们将采用第一种解决方案。您的解决方案帮助我了解了如果我们有早期版本,该如何做。