使用多个设备确定 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_Value
和 Last_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 获得一个额外的行,总时间这些行
我有一个 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_Value
和 Last_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 获得一个额外的行,总时间这些行