【问题标题】:Creating Hourly average based on 2 minutes before and after of time instantaneous in PostgreSQL在 PostgreSQL 中基于瞬时时间前后 2 分钟创建每小时平均值
【发布时间】:2023-03-22 13:03:02
【问题描述】:

我有一个采样频率为 2 分钟的时态数据库,我想将瞬时每小时值提取为每天 00:00、01:00、02、... 23。
所以,我想从平均值中得到平均值:

HH-1:58、HH:00 和 HH:02 = HH 点钟的平均值

HH-1:59、HH:01 和 HH:03 = HH 点钟的平均值

样本数据1:

9/28/2007 23:51 -1.68
9/28/2007 23:53 -1.76
9/28/2007 23:55 -1.96
9/28/2007 23:57 -2.02
9/28/2007 23:59 -1.92
9/29/2007 0:01  -1.64
9/29/2007 0:03  -1.76
9/29/2007 0:05  -1.83
9/29/2007 0:07  -1.86
9/29/2007 0:09  -1.94

预期结果:

午夜 00 点:

(-1.92+-1.64+-1.76)/3

样本数据2:

9/28/2007 23:54 -1.44
9/28/2007 23:56 -1.58
9/28/2007 23:58 -2.01
9/29/2007 0:00  -1.52
9/29/2007 0:02  -1.48
9/29/2007 0:04  -1.46

预期结果:

(-2.01+-1.52+-1.48)/3

【问题讨论】:

    标签: postgresql average temporal-database


    【解决方案1】:
    SELECT  hr, ts, aval
    FROM    (
            SELECT  *, ROW_NUMBER() OVER (PARTITION BY hr ORDER BY ts) rn
            FROM    (
                    SELECT  *,
                            DATE_TRUNC('hour', ts) AS hr,
                            AVG(value) OVER (ORDER BY ts ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS aval
                    FROM    mytable
                    ) q
            ) q
    WHERE   rn = 1
    

    【讨论】:

      【解决方案2】:

      PostgreSQL 的window functions 使涉及相邻行的任何事情都比以前简单得多。未尝试但应该大致正确:

      select
        date_trunc('hour', newest_time) as average_time,
        (oldest_temp + middle_temp + newest_temp) / 3 as average_temp
      from (
        select
          date_trunc('hour', sample_time) as average_time,
          lag(sample_time, 2) over w as oldest_time,
          lag(sample_time, 1) over w as middle_time,
          sample_time as newest_time,
          lag(sample_temp, 2) over w as oldest_temp,
          lag(sample_temp, 1) over w as middle_temp,
          sample_temp as newest_temp
        from
          samples
        window
          w as (order by sample_time)
      ) as s
      where
        oldest_time = newest_time - '4 minutes'::interval and
        middle_time = newest_time - '2 minutes'::interval and
        extract(minute from newest_time) in (2, 3);
      

      我已在 where 子句中将此限制为您所描述的场景 - 最新值在 :02 或 :03,前 2 个值在 2 分钟和 4 分钟前。以防万一您丢失了一些数据,否则会产生奇怪的结果,例如在更长的时间间隔内进行平均。

      【讨论】:

      • 我遇到了这个错误。错误:在“超过”SQL 状态处或附近出现语法错误:42601 字符:110
      • 试试这个版本,它为我运行(虽然我没有输入任何数据来尝试它)。好像我有点误解了over;它将范围应用于单个 select 子句,而不是查询中的每个窗口函数。我不确定是否可以将其应用于where,所以我使用了一个子查询来代替。
      • 啊,不可能从 WHERE 使用窗口函数,因为首先发生 WHERE 过滤:“窗口函数考虑的行是查询的 FROM 子句生成的“虚拟表”的行由其 WHERE、GROUP BY 和 HAVING 子句(如果有)过滤”。所以子查询是必要的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-17
      • 2023-03-23
      相关资源
      最近更新 更多