I'm trying to write a query that will give all the SensorID
and LocID
that have five consecutive datetime
rows, ie the difference between them is 1 hour and voltage is >= 6. I can use LAG and get the difference in minutes, but how to select the consecutive rows?
Input table:
SensorID LocID DateTime Voltage
-------------------------------
100 200 1/23/2019 13:00 6
100 200 1/23/2019 12:00 8
100 200 1/23/2019 11:00 6
100 200 1/23/2019 10:00 7
100 200 1/23/2019 9:00 8
101 201 1/23/2019 10:00 8
101 201 1/23/2019 9:00 1
101 201 1/23/2019 8:00 2
101 201 1/23/2019 6:00 8
101 201 1/23/2019 5:00 1
103 203 1/23/2019 11:00 10
103 203 1/23/2019 10:00 11
103 203 1/23/2019 9:00 8
103 203 1/23/2019 8:00 9
103 203 1/23/2019 7:00 9
Required output:
SensorID LocID DateTime Voltage
-------------------------------
100 200 01/23/19 1 PM 6
100 200 01/23/19 12 PM 8
100 200 01/23/19 11 AM 6
100 200 01/23/19 10 AM 7
100 200 01/23/19 9 AM 8
103 203 01/23/19 11 AM 10
103 203 01/23/19 10 AM 11
103 203 01/23/19 9 AM 8
103 203 01/23/19 8 AM 9
103 203 01/23/19 7 AM 9
use tempdb
go
Create Table #Input
(
SensorID int
, LocID int
, DateTime datetime
, Voltage float
)
Insert Into #Input
Select 100,200,'1/23/2019 13:00',6 Union All
Select 100,200,'1/23/2019 12:00',8 Union All
select 100,200,'1/23/2019 11:00',6 Union All
Select 100,200,'1/23/2019 10:00',7 Union All
Select 100,200,'1/23/2019 9:00',8 Union All
Select 101,201,'1/23/2019 10:00',8 Union All
Select 101,201,'1/23/2019 9:00',1 Union All
Select 101,201,'1/23/2019 8:00',2 Union All
Select 101,201,'1/23/2019 6:00',8 Union All
Select 101,201,'1/23/2019 5:00',1 Union All
Select 103,203,'1/23/2019 11:00',10 Union All
Select 103,203,'1/23/2019 10:00',11 Union All
Select 103,203,'1/23/2019 9:00',8 Union All
Select 103,203,'1/23/2019 8:00',9 Union All
Select 103,203,'1/23/2019 7:00',9
Select * from #Input
drop table #Input
go
You can use the OFFSET
argument of LAG
to check 4 rows back to make it a 5 row window (counting the current). EG: lag(Column,Offset,Default)
where column is the column, offset is the number of rows back, and default is what to return if the condition fails ( NULL
by default).
;with cte as(
select
*
,LogicCheck = abs(datediff(hour,[DateTime],lag([DateTime],4) over (partition by SensorID order by [DateTime])))
from #Input
)
select *
from #Input
where SensorID in (select SensorID from cte where LogicCheck = 4)
This works with your sample data but if there are larger windows, you'll want to account for that. See this added sample data and method for taking care of the larger windows.
use tempdb
go
Create Table #Input
(
SensorID int
, LocID int
, DateTime datetime
, Voltage float
)
Insert Into #Input
Select 100,200,'1/23/2019 13:00',6 Union All
Select 100,200,'1/23/2019 12:00',8 Union All
select 100,200,'1/23/2019 11:00',6 Union All
Select 100,200,'1/23/2019 10:00',7 Union All
Select 100,200,'1/23/2019 9:00',8 Union All
Select 101,201,'1/23/2019 10:00',8 Union All
Select 101,201,'1/23/2019 9:00',1 Union All
Select 101,201,'1/23/2019 8:00',2 Union All
Select 101,201,'1/23/2019 6:00',8 Union All
Select 101,201,'1/23/2019 5:00',1 Union All
Select 103,203,'1/23/2019 11:00',10 Union All
Select 103,203,'1/23/2019 10:00',11 Union All
Select 103,203,'1/23/2019 9:00',8 Union All
Select 103,203,'1/23/2019 8:00',9 Union All
Select 103,203,'1/23/2019 7:00',9 Union All
Select 103,203,'1/23/2019 6:00',9 Union all --added this row which should be included
Select 103,203,'1/23/2019 4:00',9 --added this row which is a break in the time and shouldn't be returned
;with cte as(
select
*
,Seq = row_number() over (partition by SensorID order by [DateTime])
,LogicCheck = abs(datediff(hour,[DateTime],lag([DateTime],4) over (partition by SensorID order by [DateTime])))
from #Input
)
select
c.SensorID
,c.LocID
,c.DateTime
,c.Voltage
--,c.Seq
--,c.LogicCheck
from
cte c
where exists
(
select SensorID
from cte
where LogicCheck = 4
and cte.SensorID = c.SensorID
and c.Seq <= cte.Seq
and c.Seq >= cte.Seq - 4
)
drop table #Input
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.