【问题标题】:postgres: using previous row value when current row value is nullpostgres:当当前行值为空时使用前一行值
【发布时间】:2015-06-15 14:48:49
【问题描述】:

在我的应用程序中,我需要为 postgres 数据库中的数据(实际上是传感器收集的温度数据)生成数据输出(然后转换为 JSON)。

数据存储在 device_history_log 中如下(针对上午 11 点到中午之间的数据):

row_id;deviceid;sensor_value_raw;last_update
104401;20865735;21.56;"2015-06-10 11:00:14"
104432;493417852;23.9;"2015-06-10 11:00:58"
104516;20865735;21.06;"2015-06-10 11:05:14"
104578;493417852;23.7;"2015-06-10 11:06:43"
104583;20865735;21.12;"2015-06-10 11:13:21"
104601;20865735;21.18;"2015-06-10 11:17:25"
104623;493417852;22.2;"2015-06-10 11:18:21"
104642;20865735;21.25;"2015-06-10 11:21:29"
104937;20865735;21.31;"2015-06-10 11:25:33"
105081;20865735;21.37;"2015-06-10 11:33:41"
105154;20865735;21.43;"2015-06-10 11:37:45"
105303;493417852;24;"2015-06-10 11:46:09"
105358;20865735;21.62;"2015-06-10 11:49:58"

我想获得数据的 5 分钟平均值,目前我正在使用此查询:

SELECT grid.t5||'.000000' as ts, 
            CASE
                WHEN avg(t.sensor_value_raw) ISNULL THEN -1
                ELSE avg(t.sensor_value_raw) 
            END AS sensorvalue
FROM (

      SELECT date_trunc('min', time_series) as t5 
      FROM generate_series('2015-06-10 11:00:00'::timestamp, '2015-06-11 12:00:00', 
                   '5 min') as time_series

   ) grid
LEFT JOIN device_history_log t 
     ON t.last_update >= grid.t5 AND t.last_update <  grid.t5 +  interval '5 min' AND (t.deviceid = 493417852 or t.deviceid = 20865735)
GROUP  BY grid.t5
ORDER  BY grid.t5

生成的数据如下所示:

"2015-06-10 11:00:00.000000";23.8999996185303
"2015-06-10 11:05:00.000000";21.0599994659424
"2015-06-10 11:10:00.000000";21.1200008392334
"2015-06-10 11:15:00.000000";21.1800003051758
"2015-06-10 11:20:00.000000";21.25
"2015-06-10 11:25:00.000000";21.3099994659424
"2015-06-10 11:30:00.000000";21.3700008392334
"2015-06-10 11:35:00.000000";21.4300003051758
"2015-06-10 11:40:00.000000";-1
"2015-06-10 11:45:00.000000";22.8100004196167
"2015-06-10 11:50:00.000000";-1
"2015-06-10 11:55:00.000000";-1
"2015-06-10 12:00:00.000000";22.9250001907349

我需要平均值,因为有多个传感器返回报告,因此需要平均值。

我的问题是 10:40:00 而不是 -1 的值是否有可能具有先前的值,因为温度传感器仅报告温度的“变化”,因此“无数据”意味着“没有变化” '。

如果可能的话,对于第一个值为 -1(因此没有以前的数据)的值,我希望它们被删除/忽略,我可以在解析数据时执行此操作,但如果可以完成查询级别则更好。

因此我理想的结果集是这样的:

"2015-06-10 11:00:00.000000";23.8999996185303
"2015-06-10 11:05:00.000000";21.0599994659424
"2015-06-10 11:10:00.000000";21.1200008392334
"2015-06-10 11:15:00.000000";21.1800003051758
"2015-06-10 11:20:00.000000";21.25
"2015-06-10 11:25:00.000000";21.3099994659424
"2015-06-10 11:30:00.000000";21.3700008392334
"2015-06-10 11:35:00.000000";21.4300003051758
"2015-06-10 11:40:00.000000";21.4300003051758
"2015-06-10 11:45:00.000000";22.8100004196167
"2015-06-10 11:50:00.000000";22.8100004196167
"2015-06-10 11:55:00.000000";22.8100004196167
"2015-06-10 12:00:00.000000";22.9250001907349

谢谢!

【问题讨论】:

标签: postgresql


【解决方案1】:

以下查询填充原始查询结果集中的 empty 值。该方法包括根据 empty 值的数量将数据分成多个分区,并从每个分区中选择第一个(非空)值(将 * 添加到 select 以查看其工作原理)。

WITH survey AS (

    SELECT grid.t5||'.000000' as ts, 
        CASE
            WHEN avg(t.sensor_value_raw) ISNULL THEN -1
            ELSE avg(t.sensor_value_raw) 
        END AS sensorvalue
    FROM (

          SELECT date_trunc('min', time_series) as t5 
          FROM generate_series('2015-06-10 11:00:00'::timestamp, '2015-06-11 12:00:00', 
                       '5 min') as time_series

       ) grid
    LEFT JOIN device_history_log t 
         ON t.last_update >= grid.t5 AND t.last_update <  grid.t5 +  interval '5 min' AND (t.deviceid = 493417852 or t.deviceid = 20865735)
    GROUP  BY grid.t5
    ORDER  BY grid.t5)

SELECT
    ts, first_value(sensorvalue) OVER (PARTITION BY part ORDER BY ts) sensorvalue
FROM (  
    SELECT *, sum((sensorvalue != -1)::int) OVER (ORDER BY ts) part
    FROM survey) alias

【讨论】:

  • 谢谢@klin,但我需要平均值,因为有不止一个 deviceid(温度传感器)报告回来。我已更新数据以使其更加明确。
  • @Kostas:查看更改后的答案。
  • 谢谢@klin!这太棒了!有效!
猜你喜欢
  • 2016-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-03
  • 2015-07-09
  • 2020-05-10
  • 2016-01-17
  • 1970-01-01
相关资源
最近更新 更多