使用多个设备确定 table 中设备特定状态的持续时间

determine duration of certain state of a device in table with multiple devices

我有一个 table,其中包含设备 ID、设备状态(已绕过)和时间戳(Regtime)

+----------+--------+-----------------+
| DeviceId | Bypass |     RegTime     |
+----------+--------+-----------------+
|       14 |      0 | 30-5-2018 02:14 |
|       12 |      0 | 30-5-2018 02:14 |
|       14 |      0 | 30-5-2018 02:15 |
|       14 |      0 | 30-5-2018 02:15 |
|       12 |      0 | 30-5-2018 02:15 |
|       12 |      0 | 30-5-2018 02:15 |
|       14 |      0 | 30-5-2018 02:16 |
|       12 |      0 | 30-5-2018 02:16 |
|       14 |      1 | 30-5-2018 02:17 |
|       12 |      0 | 30-5-2018 02:17 |
|       14 |      1 | 30-5-2018 02:18 |
|       12 |      0 | 30-5-2018 02:18 |
|       14 |      1 | 30-5-2018 02:19 |
|       12 |      0 | 30-5-2018 02:19 |
|       14 |      0 | 30-5-2018 02:20 |
|       12 |      0 | 30-5-2018 02:20 |
|       14 |      0 | 30-5-2018 02:21 |
|       12 |      0 | 30-5-2018 02:21 |
|       14 |      0 | 30-5-2018 02:22 |
|       12 |      1 | 30-5-2018 02:22 |
|       14 |      0 | 30-5-2018 02:23 |
|       12 |      1 | 30-5-2018 02:23 |
|       14 |      0 | 30-5-2018 02:24 |
|       12 |      0 | 30-5-2018 02:24 |
+----------+--------+-----------------+

现在我需要确定设备处于旁路状态(旁路 = 0)的时间。

我已经尝试了几种使用窗口和 First_ValueLast_Value 的方法,但这里的问题似乎是我只能按 DeviceId 进行分区。

所以当一个设备处于 Bypass 然后从它出来时,first_value 仍然是所有设备的 first_value

假设你的意思是这样的。如果没有,则提供 plaidDK 要求的预期结果:

USE Sandbox;
GO

CREATE TABLE Device (DeviceID int,
                     Bypass bit,
                     RegTime datetime2(0));
GO
INSERT INTO Device
VALUES
(14,0,'2018-05-30T02:14:00.000'),
(12,0,'2018-05-30T02:14:00.000'),
(14,0,'2018-05-30T02:15:00.000'),
(14,0,'2018-05-30T02:15:00.000'),
(12,0,'2018-05-30T02:15:00.000'),
(12,0,'2018-05-30T02:15:00.000'),
(14,0,'2018-05-30T02:16:00.000'),
(12,0,'2018-05-30T02:16:00.000'),
(14,1,'2018-05-30T02:17:00.000'),
(12,0,'2018-05-30T02:17:00.000'),
(14,1,'2018-05-30T02:18:00.000'),
(12,0,'2018-05-30T02:18:00.000'),
(14,1,'2018-05-30T02:19:00.000'),
(12,0,'2018-05-30T02:19:00.000'),
(14,0,'2018-05-30T02:20:00.000'),
(12,0,'2018-05-30T02:20:00.000'),
(14,0,'2018-05-30T02:21:00.000'),
(12,0,'2018-05-30T02:21:00.000'),
(14,0,'2018-05-30T02:22:00.000'),
(12,1,'2018-05-30T02:22:00.000'),
(14,0,'2018-05-30T02:23:00.000'),
(12,1,'2018-05-30T02:23:00.000'),
(14,0,'2018-05-30T02:24:00.000'),
(12,0,'2018-05-30T02:24:00.000');
GO
WITH CTE AS(
    SELECT *,
           ROW_NUMBER() OVER (PARTITION BY DeviceID ORDER BY RegTime ASC) AS RN
    FROM Device
    WHERE Bypass = 1)
SELECT DeviceID,
       Bypass,
       RegTime
FROM CTE
WHERE RN = 1 ;

GO
DROP TABLE Device;

这是一个间隙和孤岛类型的问题,设备处于状态 1 的状态是孤岛。

See updated live demo 您可以使用如下查询来获取数据

;with numberedT as 
(
    select *, 
    rn =ROW_NUMBER() over(Partition by deviceId order by RegTime), 
    rn2=ROW_NUMBER() over(Partition by deviceId,Bypass order by RegTime)
    from t 
)

select 
    deviceid,
    BypassStart=min(Regtime),
    BypassEnd = max(Regtime),
    TimeInBypassState=datediff(mi,min(Regtime),max(Regtime))
from numberedT
group by deviceid,rn2-rn, Bypass
Having Bypass=1
order by deviceid

如果您需要确定设备内旁路 1 的持续时间,您可以这样做:

示例数据

create table #temp
(deviceid int,bypass int, regtime datetime)

insert into #temp 
values
(14 , 0 ,'2018-05-30 02:14'),
(12 , 0 ,'2018-05-30 02:14'),
(14 , 0 ,'2018-05-30 02:15'),
(14 , 0 ,'2018-05-30 02:15'),
(12 , 0 ,'2018-05-30 02:15'),
(12 , 0 ,'2018-05-30 02:15'),
(14 , 0 ,'2018-05-30 02:16'),
(12 , 0 ,'2018-05-30 02:16'),
(14 , 1 ,'2018-05-30 02:17'),
(12 , 0 ,'2018-05-30 02:17'),
(14 , 1 ,'2018-05-30 02:18'),
(12 , 0 ,'2018-05-30 02:18'),
(14 , 1 ,'2018-05-30 02:19'),
(12 , 0 ,'2018-05-30 02:19'),
(14 , 0 ,'2018-05-30 02:20'),
(12 , 0 ,'2018-05-30 02:20'),
(14 , 0 ,'2018-05-30 02:21'),
(12 , 0 ,'2018-05-30 02:21'),
(14 , 0 ,'2018-05-30 02:22'),
(12 , 1 ,'2018-05-30 02:22'),
(14 , 0 ,'2018-05-30 02:23'),
(12 , 1 ,'2018-05-30 02:23'),
(14 , 0 ,'2018-05-30 02:24'),
(12 , 0 ,'2018-05-30 02:24')

SQL 脚本

select x.deviceid,x.bypass,regtime,case when x.bypass = rn then DATEDIFF(SS,regtime,maxtime) else 0 end as DurationInSeconds from (
select *,ROW_NUMBER()over(partition by a.deviceid,a.bypass order by regtime) as rn
from #temp a
) x

cross apply (select MAX(regtime) as maxtime,deviceid,bypass from #temp b where  B.bypass = 1 and x.deviceid = B.deviceid   group by deviceid,bypass ) c

如果您只想要有关设备信息的信息:

SQL2

select x.deviceid,x.bypass,case when x.bypass = rn then DATEDIFF(SS,regtime,maxtime) else 0 end as DurationInSeconds from (
select *,ROW_NUMBER()over(partition by a.deviceid,a.bypass order by regtime) as rn
from #temp a
) x

cross apply (select MAX(regtime) as maxtime,deviceid,bypass from #temp b where  B.bypass = 1 and x.deviceid = B.deviceid and rn= 1 and x.bypass = 1   group by deviceid,bypass ) c

输出应该是这样的:

|设备编号 |旁路开始 |旁路结束 |旁路持续时间 |

|------------|----------------|-------------- --|----------------|

| 12 | 2018 年 5 月 30 日 02:22 | 2018 年 5 月 30 日 02:23 | 1 |

| 14 | 30-5-2018 02:17 | 2018 年 5 月 30 日 02:19 | 2 |

但是,当 Bypass = 1 和 DeviceId = 14 的另一次出现出现在一些有说服力的记录中时,并且在 Bypass = 1 发生之间,我应该为该 Device 获得一个额外的行,总时间这些行