SQL查找在特定时间内高于阈值的值

SQL查找在特定时间内高于阈值的值,sql,postgresql,gaps-and-islands,Sql,Postgresql,Gaps And Islands,考虑下表: create table measurement ( datetime timestamp, temperature numeric(5,2) ); 我想在PostgreSQL中创建一个SQL查询,该查询提取温度高于50°C至少30分钟的行,最好知道温度从何时到何时实际高于50°C。示例数据如下: datetime temperature ------------------- ----------- 2017-03-15

考虑下表:

create table measurement (
    datetime     timestamp,
    temperature  numeric(5,2)
);
我想在PostgreSQL中创建一个SQL查询,该查询提取温度高于50°C至少30分钟的行,最好知道温度从何时到何时实际高于50°C。示例数据如下:

datetime               temperature
-------------------    -----------
2017-03-15 19:00:10    49.56
2017-03-15 19:15:10    52.81
2017-03-15 19:30:10    49.00
2017-03-15 19:45:10    52.88
2017-03-15 20:00:10    49.56
2017-03-15 20:15:10    49.13
2017-03-15 20:30:10    51.31   <--
2017-03-15 20:45:10    52.06   <--
2017-03-15 21:00:10    50.50   <--
2017-03-15 21:15:10    50.50   <--
2017-03-15 21:30:10    49.38
2017-03-15 21:45:10    47.44
2017-03-15 22:00:10    46.19
2017-03-15 22:15:10    45.44
2017-03-15 22:30:10    50.25
2017-03-15 22:45:10    48.56
2017-03-15 23:00:10    51.25   <--
2017-03-15 23:15:10    50.44   <--
2017-03-15 23:30:10    50.63   <--
2017-03-15 23:45:10    46.75

所以,温度高于50的第一身份组。这是一个缺口和孤岛问题。然后,您可以对该岛进行汇总,以获得所需信息:

select min(datetime), max(datetime), count(*) as numrecs, avg(temperature)
from (select t.*,
             row_number() over (order by datetime) as seqnum,
             row_number() over (partition by (temperature >= 50)::int 
                                order by datetime) as seqnum_t
      from t
     ) t
where temperature >= 50
group by (seqnum - seqnum_t)
having max(datetime) >= min(datetime) + interval '30' minute;

Gordon的解决方案可以简化为一个OLAP函数:

select min(datetime), max(datetime), count(*) as numrecs, avg(temperature)
from
 (
   select datetime, temperature, 
      -- previous time when temperature was < 50
      -- same time for all rows with a temp >= 50
      max(case when temperature < 50 then datetime end)
      over (order by datetime
            rows unbounded preceding) as prevlow
   from measurement
 ) as dt
where temperature >= 50
group by prevlow
having max(datetime) >= min(datetime) + interval '30' minute;

你可能正在寻找高于50摄氏度的记录,而在接下来的30分钟内没有低于50摄氏度的记录。戈登,如果你没有匹配条款,那就酷了!很好的解决方案。我喜欢。