Postgres时间平均数据

时间:2016-05-13 04:13:21

标签: sql postgresql

我们使用Postgres记录来自我们流程的数据。我们数据库的一个例子如下:

CREATE TABLE Data
("time_stamp" timestamp, "pressure" numeric, "temperature" numeric, "flow" numeric);

INSERT INTO Data
("time_stamp", "pressure", "temperature", "flow")
VALUES
('2016-05-12 20:42:24', 97.68, 9.02564, 2.24664),
('2016-05-12 20:42:25', 97.68, 9.02564, 2.24054),
('2016-05-12 20:42:26', 122.1, 9.01832, 2.24054),
('2016-05-12 20:42:27', 122.1, 9.01099, 2.23443),
('2016-05-12 20:42:28', 97.68, 9.01099, 2.23443),
('2016-05-12 20:42:29', 122.1, 9.01099, 2.24054),
('2016-05-12 20:42:30', 97.68, 9.01099, 2.23443),
('2016-05-12 20:42:31', 122.1, 9.01099, 2.23443),
('2016-05-12 20:42:32', 122.1, 9.01832, 2.24054),
('2016-05-12 20:42:33', 122.1, 9.01832, 2.23443);

我要做的是让Postgres(使用pgAdminIII)生成任意时间片的平均数据,比如5秒。它将输出该五秒切片的平均时间,压力,温度和流量列。此数据将有两个条目,时间条目为' 2016-05-12 20:42:26'和' 2016-05-12 20:42:31'。

1 个答案:

答案 0 :(得分:0)

这是一个解决方案,这不是最好的,但有点有用。

SELECT timestamp without time zone '1970-01-01' + cast(avg(extract(epoch from time_stamp))::text as interval),
       sub.press,
       sub.temp,
       sub.flow 
FROM data d join (
     SELECT
           (extract(seconds from time_stamp)/5)::integer as num,
           avg(pressure) as press,
           avg(temperature) as temp,
           avg(flow) as flow
      FROM
           data
      group by 1) sub on sub.num=(extract(second from d.time_stamp)/5)::integer
group by sub.press,sub.temp,sub.flow
order by 1

子选择从数据表中选择数据并将其分组5秒。时间戳需要外部选择才能获得“平均”。我认为使用函数应该更容易。

编辑: 这是我为此写的功能。假设每秒只有一行。

您需要先创建自定义类型:

CREATE TYPE t_data AS
(
  time_stamp timestamp,
  pressure numeric,
  temp numeric,
  flow numeric);

这是功能:

CREATE OR REPLACE FUNCTION dataCheck ( timeInterval integer ) RETURNS setof t_data AS $BODY$
DECLARE
  pressure numeric[];
  temp numeric[];
  flow numeric[];
  rec record;
  i integer default 1;
  ret t_data;
BEGIN
  for rec in select * from data order by time_stamp
  loop
    pressure[i]=rec.pressure;
    temp[i]=rec.temp;
    flow[i]=rec.flow;

    if i=(timeInterval/2 + case when timeInterval%2 <> 0 then 1 else 0 end) then
      ret.time_stamp=rec.time_stamp;
    end if;
    if i=timeInterval then
      i=0;
      ret.pressure=avg((select avg(a) from unnest(pressure) as a));
      ret.temp=avg((select avg(a) from unnest(temp) as a));
      ret.flow=avg((select avg(a) from unnest(flow) as a));
      return next ret;
    end if;

    i=i+1;
  end loop;

return ;

end;$BODY$ LANGUAGE plpgsql;

这就是你执行它的方式:

SELECT * from dataCheck(5);

该函数将每“5”行返回平均数据。