Sql-server – Find the first datetime interval

sql serversql-server-2005

I have a table in SQL with a column Recordtime and valueasreal

RecordTime           ValueAsReal
2015-11-30 12:59:00  195,6907
2015-11-30 13:00:00  203,8667
2015-11-30 13:01:00  198,0907
2015-11-30 13:02:00  198,3573
2015-11-30 13:03:00  208,064
2015-11-30 13:04:00  211,3066
2015-11-30 13:05:00  219,36
2015-11-30 13:06:00  233,4453
2015-11-30 13:07:00  232,8106
2015-11-30 13:08:00  217,872
2015-11-30 13:09:00  214,464
2015-11-30 13:10:00  200,0587
2015-11-30 13:11:00  173,776
2015-11-30 13:12:00  181,1787

I need to find the first 5 minute interval where the valueasreal >= 200, in this case the query would return

2015-11-30 13:03:00  208,064
2015-11-30 13:04:00  211,3066
2015-11-30 13:05:00  219,36
2015-11-30 13:06:00  233,4453
2015-11-30 13:07:00  232,8106
2015-11-30 13:08:00  217,872

OR

StartRecordTime                 EndRecordTime              AVG(ValueAsreal)
2015-11-30 13:03:00             2015-11-30 13:08:00        220.476

Best Answer

You can find the min value for RecordTime where there are 6 consecutive rows by using a correlated query doing top(6) and then count the number of rows that is greater than or equal to 200.

Use that min value for RecordTime against the table to get the 6 consecutive rows that you want.

-- Setup table to test on
declare @T table
(
  RecordTime datetime primary key,
  ValueAsReal decimal(7, 4)
);

-- Add some data
insert into @T(RecordTime, ValueAsReal) 
select '2015-11-30 12:59:00',  195.6907 union all
select '2015-11-30 13:00:00',  203.8667 union all
select '2015-11-30 13:01:00',  198.0907 union all
select '2015-11-30 13:02:00',  198.3573 union all
select '2015-11-30 13:03:00',  208.064  union all
select '2015-11-30 13:04:00',  211.3066 union all
select '2015-11-30 13:05:00',  219.36   union all
select '2015-11-30 13:06:00',  233.4453 union all
select '2015-11-30 13:07:00',  232.8106 union all
select '2015-11-30 13:08:00',  217.872  union all
select '2015-11-30 13:09:00',  214.464  union all
select '2015-11-30 13:10:00',  200.0587 union all
select '2015-11-30 13:11:00',  173.776  union all
select '2015-11-30 13:12:00',  181.1787;

-- Desired number of rows
declare @NumRows int;
set @NumRows = 6;

-- Min value to look for
declare @ValueAsReal decimal(7, 4);
set @ValueAsReal = 200;


-- Get the first @NumRows rows where RecordTime is greater than or equal to 
-- the min value for RecordTime where there are 6
-- consecutive values for ValueAsReal greater than or equal to @ValueAsReal
select top(@NumRows) 
  T.RecordTime,
  T.ValueAsReal
from @T as T
where T.RecordTime >= (
                      select top(1) T1.RecordTime
                      from @T as T1
                      where (
                            select count(*)
                            from (
                                 select top(@NumRows) 
                                   T2.RecordTime, 
                                   T2.ValueAsReal
                                 from @T as T2
                                 where T1.RecordTime <= T2.RecordTime
                                 order by T2.RecordTime
                                 ) as T3
                            where T3.ValueAsReal >= @ValueAsReal
                            ) = @NumRows and
                            T1.ValueAsReal >= @ValueAsReal
                      order by T1.RecordTime
                      )
order by T.RecordTime;

Query plan:

enter image description here