SQL 列出值大于特定值的周期
SQL list periodes where value is more then a spesific value
我有一个 table 这样的 Id、DateTime、Device、Value。
我需要找到 Value >=5 和 Return 这段时间的 From 和 To dateTime 的所有时间段。
该设备可以是一个温度传感器,我需要一个 From/To 列表,其中温度已经超过 5。
如果我们认为它是一个温度传感器并且它每 5 分钟记录一次。 table 将是这样的:
Id DateTime Device Value
--------------------------------
1 2015.09.01 09:10 T1 3,2
2 2015.09.01 09:15 T1 5,2
3 2015.09.01 09:20 T1 6,2
4 2015.09.01 09:25 T1 5,8
5 2015.09.01 09:30 T1 3,2
6 2015.09.01 09:35 T1 1,2
7 2015.09.01 09:40 T1 5,6
8 2015.09.01 09:45 T1 6,1
9 2015.09.01 09:50 T1 5,0
10 2015.09.01 09:55 T1 2,0
我试图找到的时间段是从 09:15 到 09:25 以及从 09:40 到 09:50。
在 SQL Server 2014 中是否有一种聪明的方法可以做到这一点?
是的,有一种聪明的方法可以做到这一点。
看看 'PARTITION BY' 和 'OVER' 子句。
使用这些功能,我相信您应该能够按时间段对数据进行分区(分组)并获取每个组的 DateTime 列的 MIN 和 MAX 值。
这是获得所需结果的一种方式:
SELECT MIN([DateTime]) AS StartPeriod, MAX([DateTime]) AS EndPeriod,
Device
FROM (
SELECT Id, [DateTime], Device, Value,
ROW_NUMBER() OVER (PARTITION BY Device ORDER BY Id) -
COUNT(CASE WHEN Value >= 5 THEN 1 END)
OVER (PARTITION BY Device ORDER BY Id) AS grp
FROM mytable ) AS t
WHERE t.Value >= 5
GROUP BY Device, grp
如果您想每天获得 Start
- End
个经期,您可能需要 PARTITION BY Device, [DateTime]
。
这基本上是 answered before,诀窍是您已经连续连续地订购了 id
列。如果那不存在,您需要做更多的前期工作才能使减法正常工作。
select * into #tempTable from (
select Id = 1,[DateTime] = cast('2015.09.01 09:10' as datetime), device = 'T1', value = 3.2
union all select 2,cast('2015.09.01 09:15' as datetime),'T1',5.2
union all select 3,cast('2015.09.01 09:20' as datetime),'T1',6.2
union all select 4,cast('2015.09.01 09:25' as datetime),'T1',5.8
union all select 5,cast('2015.09.01 09:30' as datetime),'T1',3.2
union all select 6,cast('2015.09.01 09:35' as datetime),'T1',1.2
union all select 7,cast('2015.09.01 09:40' as datetime),'T1',5.6
union all select 8,cast('2015.09.01 09:45' as datetime),'T1',6.1
union all select 9,cast('2015.09.01 09:50' as datetime),'T1',5
union all select 10,cast('2015.09.01 09:55' as datetime),'T1',2) A
with T as (select *, row_number() over (order by id) - id as grp
from #tempTable
where value >=5
)
select [to] = min(T.Datetime), [from] = max(T.DateTime)
from T
group by T.grp
order by T.grp
输出为
to from
2015-09-01 09:40:00.000 2015-09-01 09:50:00.000
2015-09-01 09:15:00.000 2015-09-01 09:25:00.000
(我必须进行一些转换才能使您的 number/date 格式适合我)
我一直在使用 table 用户定义函数,该函数将请求的日期作为参数,函数内的游标允许填充返回的 table,如下所示:
CREATE TABLE sensor (id int not null identity(1,1) primary key,
measureDate datetime, sensor nvarchar(10), measure float)
INSERT sensor (measureDate, sensor, measure) VALUES
('2015-09-01 09:10', 'T1', '3.2'), ('2015-09-01 09:15', 'T1', '5.2'),
('2015-09-01 09:20', 'T1', '6.2'), ('2015-09-01 09:25', 'T1', '5.8'),
('2015-09-01 09:30', 'T1', '3.2'), ('2015-09-01 09:35', 'T1', '1.2'),
('2015-09-01 09:40', 'T1', '5.6'), ('2015-09-01 09:45', 'T1', '6.1'),
('2015-09-01 09:50', 'T1', '5.0'), ('2015-09-01 09:55', 'T1', '2.0')
GO
CREATE FUNCTION [dbo].[getTimeSpansBelowMaxTemp] (@measureDate date)
RETURNS @timeSpans TABLE (fromTime time, toTime time) AS BEGIN
DECLARE @measure float, @currentMeasure float = NULL
DECLARE @measureTime time, @fromMeasureTime time, @toMeasureTime time
DECLARE yourCursor CURSOR FOR
SELECT CAST(measureDate AS time), measure
FROM sensor
WHERE CAST(measureDate as date) = @measureDate
OPEN yourCursor
FETCH NEXT FROM yourCursor INTO @measureTime, @measure
WHILE (@@FETCH_STATUS = 0) BEGIN -- Loops on all the measures of the given day
IF @measure >= 5.0 BEGIN
IF @currentMeasure IS NULL BEGIN -- Start of a period
SET @currentMeasure = @measure
SET @fromMeasureTime = @measureTime
END
SET @toMeasureTime = @measureTime
END
ELSE BEGIN
IF @currentMeasure IS NOT NULL BEGIN -- End of a period
INSERT INTO @timeSpans VALUES (@fromMeasureTime, @toMeasureTime)
SET @currentMeasure = NULL
END
END
FETCH NEXT FROM yourCursor INTO @measureTime, @measure
END
CLOSE yourCursor
DEALLOCATE yourCursor
RETURN
END
GO
select * from dbo.[getTimeSpansBelowMaxTemp]('2015-09-01')
我有一个 table 这样的 Id、DateTime、Device、Value。 我需要找到 Value >=5 和 Return 这段时间的 From 和 To dateTime 的所有时间段。 该设备可以是一个温度传感器,我需要一个 From/To 列表,其中温度已经超过 5。
如果我们认为它是一个温度传感器并且它每 5 分钟记录一次。 table 将是这样的:
Id DateTime Device Value
--------------------------------
1 2015.09.01 09:10 T1 3,2
2 2015.09.01 09:15 T1 5,2
3 2015.09.01 09:20 T1 6,2
4 2015.09.01 09:25 T1 5,8
5 2015.09.01 09:30 T1 3,2
6 2015.09.01 09:35 T1 1,2
7 2015.09.01 09:40 T1 5,6
8 2015.09.01 09:45 T1 6,1
9 2015.09.01 09:50 T1 5,0
10 2015.09.01 09:55 T1 2,0
我试图找到的时间段是从 09:15 到 09:25 以及从 09:40 到 09:50。
在 SQL Server 2014 中是否有一种聪明的方法可以做到这一点?
是的,有一种聪明的方法可以做到这一点。
看看 'PARTITION BY' 和 'OVER' 子句。
使用这些功能,我相信您应该能够按时间段对数据进行分区(分组)并获取每个组的 DateTime 列的 MIN 和 MAX 值。
这是获得所需结果的一种方式:
SELECT MIN([DateTime]) AS StartPeriod, MAX([DateTime]) AS EndPeriod,
Device
FROM (
SELECT Id, [DateTime], Device, Value,
ROW_NUMBER() OVER (PARTITION BY Device ORDER BY Id) -
COUNT(CASE WHEN Value >= 5 THEN 1 END)
OVER (PARTITION BY Device ORDER BY Id) AS grp
FROM mytable ) AS t
WHERE t.Value >= 5
GROUP BY Device, grp
如果您想每天获得 Start
- End
个经期,您可能需要 PARTITION BY Device, [DateTime]
。
这基本上是 answered before,诀窍是您已经连续连续地订购了 id
列。如果那不存在,您需要做更多的前期工作才能使减法正常工作。
select * into #tempTable from (
select Id = 1,[DateTime] = cast('2015.09.01 09:10' as datetime), device = 'T1', value = 3.2
union all select 2,cast('2015.09.01 09:15' as datetime),'T1',5.2
union all select 3,cast('2015.09.01 09:20' as datetime),'T1',6.2
union all select 4,cast('2015.09.01 09:25' as datetime),'T1',5.8
union all select 5,cast('2015.09.01 09:30' as datetime),'T1',3.2
union all select 6,cast('2015.09.01 09:35' as datetime),'T1',1.2
union all select 7,cast('2015.09.01 09:40' as datetime),'T1',5.6
union all select 8,cast('2015.09.01 09:45' as datetime),'T1',6.1
union all select 9,cast('2015.09.01 09:50' as datetime),'T1',5
union all select 10,cast('2015.09.01 09:55' as datetime),'T1',2) A
with T as (select *, row_number() over (order by id) - id as grp
from #tempTable
where value >=5
)
select [to] = min(T.Datetime), [from] = max(T.DateTime)
from T
group by T.grp
order by T.grp
输出为
to from
2015-09-01 09:40:00.000 2015-09-01 09:50:00.000
2015-09-01 09:15:00.000 2015-09-01 09:25:00.000
(我必须进行一些转换才能使您的 number/date 格式适合我)
我一直在使用 table 用户定义函数,该函数将请求的日期作为参数,函数内的游标允许填充返回的 table,如下所示:
CREATE TABLE sensor (id int not null identity(1,1) primary key,
measureDate datetime, sensor nvarchar(10), measure float)
INSERT sensor (measureDate, sensor, measure) VALUES
('2015-09-01 09:10', 'T1', '3.2'), ('2015-09-01 09:15', 'T1', '5.2'),
('2015-09-01 09:20', 'T1', '6.2'), ('2015-09-01 09:25', 'T1', '5.8'),
('2015-09-01 09:30', 'T1', '3.2'), ('2015-09-01 09:35', 'T1', '1.2'),
('2015-09-01 09:40', 'T1', '5.6'), ('2015-09-01 09:45', 'T1', '6.1'),
('2015-09-01 09:50', 'T1', '5.0'), ('2015-09-01 09:55', 'T1', '2.0')
GO
CREATE FUNCTION [dbo].[getTimeSpansBelowMaxTemp] (@measureDate date)
RETURNS @timeSpans TABLE (fromTime time, toTime time) AS BEGIN
DECLARE @measure float, @currentMeasure float = NULL
DECLARE @measureTime time, @fromMeasureTime time, @toMeasureTime time
DECLARE yourCursor CURSOR FOR
SELECT CAST(measureDate AS time), measure
FROM sensor
WHERE CAST(measureDate as date) = @measureDate
OPEN yourCursor
FETCH NEXT FROM yourCursor INTO @measureTime, @measure
WHILE (@@FETCH_STATUS = 0) BEGIN -- Loops on all the measures of the given day
IF @measure >= 5.0 BEGIN
IF @currentMeasure IS NULL BEGIN -- Start of a period
SET @currentMeasure = @measure
SET @fromMeasureTime = @measureTime
END
SET @toMeasureTime = @measureTime
END
ELSE BEGIN
IF @currentMeasure IS NOT NULL BEGIN -- End of a period
INSERT INTO @timeSpans VALUES (@fromMeasureTime, @toMeasureTime)
SET @currentMeasure = NULL
END
END
FETCH NEXT FROM yourCursor INTO @measureTime, @measure
END
CLOSE yourCursor
DEALLOCATE yourCursor
RETURN
END
GO
select * from dbo.[getTimeSpansBelowMaxTemp]('2015-09-01')