PostgreSQL聚合和列值偏差的平均值

时间:2014-07-16 18:46:14

标签: sql postgresql

我想知道psql中是否有可能获得一组符合此条件的行

表        1/0 23无时区的时间戳

让我们想象一组数据

1  12 2014-07-14 09:01:00
1  13 2014-07-14 09:02:00
1  14 2014-07-14 09:03:00
1  15 2014-07-14 09:04:00
0  16 2014-07-14 09:05:00
0  17 2014-07-14 09:06:00
0  18 2014-07-14 09:07:00
1  17 2014-07-14 09:08:00
1  16 2014-07-14 09:09:00

我想按状态检索数据组,但保持日期顺序和状态更改。

即:

1 <avg temp> <avg date> (calculated over the first 4 rows)
0 <avg temp> <avg date> (calculated for the 3 rows with 0)
1 <avg temp> <avg date> (calculated for the last 2 rows)

基本上1/0意味着加热器开/关,我想 计算AVG温度,但按此加热器的状态分组

P.S:

显然是一个简单的选择avg(temp),状态来自日志组的状态 不会成功,它只会返回1/0值,而不是范围和开/关之间的变化

另一个很好处理的案例是保持每个状态变化的第一条记录不变。

即:

1 <temp> <date> (calculated over the first)
1 <avg temp> <avg date> (calculated over the first 3 rows)
0 <temp> <date> (for the row 4)
0 <avg temp> <avg date> (from 5 to 6)
1 <temp> <date> (row 7)

1 个答案:

答案 0 :(得分:0)

是的,这是可能的。这是一种使用窗口函数的方法。它会生成一个标志,以查看一行的状态是否与上一行不同,然后执行累计总和:

select t.*, sum(statuschange) over (order by date) as grp
from (select t.*,
             (case when lag(status) over (order by date) <> status then 1
                   else 0
              end) as statuschange
      from table t
     ) t;

其余的只是在这个领域进行分组:

select status, avg(temp), min(date), max(date)
from (select t.*, sum(statuschange) over (order by date) as grp
      from (select t.*,
                   (case when lag(status) over (order by date) <> status then 1
                         else 0
                    end) as statuschange
            from table t
           ) t
     ) t
group by grp, status;

我不确定在Postgres中平均日期的最佳方式,因此这包括最小值和最大值。您的问题似乎更多地是关于定义组而不是获取日期/时间列的平均值。