如何在 Postgres 中获取时间间隔的平均值

2024-01-09

我正在使用 PostgreSQL 9.6。我有一个这样的表:

mac   sn         loc   time     date      vin1    vin2    vin3
1a34 4as11111111 aaaa  7:06:18  1/1/2018  447.42  472.32  682.59
1a34 4as11111111 aaaa  7:06:43  1/1/2018  455.97  476.25  682.59
1a34 4as11111111 aaaa  7:07:35  1/1/2018  470.88  484.2   682.5

我需要计算的平均值vin1, vin2, vin3在 300 秒(5 分钟)的时间间隔内。例如,对于范围内的日期,从第一次 (7:06:18 - 7:11:18) 开始。我可以通过此查询选择我需要的数据:

select * from table
where sn='4as11111111' and date between '2018-01-01' and '2018-01-02';

但我不知道如何按 300 秒时间间隔对其进行分组并计算平均值vin1, vin2, vin3这 5 分钟间隔的列,得到如下内容:

mac  sn          loc     time     date      vin1_av  vin2_av  vin3_av
1a34 4as11111111 aaaa   7:06:18  1/1/2018  450.0    480.32   600.59
1a34 4as11111111 aaaa   7:11:18  1/1/2018  460.0    490.25   782.59
1a34 4as11111111 aaaa   7:16:18  1/1/2018  470.88   500.2    600.5

任何帮助将不胜感激。


数据库设计

当你can与单独的工作date and time柱子,确实比单个柱子没有优势timestamp https://www.postgresql.org/docs/current/datatype-datetime.html柱子。我会适应:

ALTER TABLE tbl ADD column ts timestamp;
UPDATE tbl SET ts = date + time;  -- assuming actual date and time types
ALTER TABLE tbl DROP column date, DROP column time;

如果日期和时间不是实际的date and time数据类型、使用to_timestamp()。有关的:

  • 在 PostgreSQL 中计算累积和 https://stackoverflow.com/questions/22841206/calculating-cumulative-sum-in-postgresql/22843199#22843199
  • 如何将“字符串”转换为“没有时区的时间戳” https://stackoverflow.com/questions/18913236/how-to-convert-string-to-timestamp-without-time-zone/18919571#18919571

Query

那么查询就简单了一些:

SELECT *
FROM  (
   SELECT sn, generate_series(min(ts), max(ts), interval '5 min') AS ts
   FROM   tbl
   WHERE  sn = '4as11111111'
   AND    ts >= '2018-01-01'
   AND    ts <  '2018-01-02'
   GROUP  BY 1
   ) grid
CROSS  JOIN LATERAL (
   SELECT round(avg(vin1), 2) AS vin1_av
        , round(avg(vin2), 2) AS vin2_av
        , round(avg(vin3), 2) AS vin3_av
   FROM   tbl
   WHERE  sn =  grid.sn
   AND    ts >= grid.ts
   AND    ts <  grid.ts + interval '5 min'
   ) avg;

数据库小提琴

在第一个子查询中生成开始时间网格grid,从第一个运行到最后一个排位赛给定时间范围内的行。

使用 a 连接到每个分区中的行LATERAL连接并立即聚合子查询中的平均值avg。由于聚集体,它always即使未找到任何条目,也会返回一行。平均值默认为NULL在这种情况下。

结果包括给定时间范围内第一个和最后一个合格行之间的所有时间段。其他各种结果组合也有意义。喜欢包括all给定时间范围内的时间段或仅具有实际值的时间段。一切可能,我必须选择一种解释。

Index

至少有这个多列索引:

CRATE INDEX foo_idx ON tbl (sn, ts);

Or on (sn, ts, vin1, vin2, vin3)允许仅索引扫描 - 如果满足一些先决条件,特别是如果表行比演示中宽得多。

密切相关:

  • CTE 上具有时间间隔的慢速 LEFT JOIN https://stackoverflow.com/questions/50221842/slow-left-join-on-cte-with-time-intervals/50224911?noredirect=1#comment87491850_50224911
  • 按任意时间间隔计算行数的最佳方法 https://stackoverflow.com/questions/15576794/best-way-to-count-records-by-arbitrary-time-intervals-in-railspostgres/15577413#15577413

根据您的原始表

按照评论中的要求和澄清 https://stackoverflow.com/questions/50261637/how-to-get-average-values-for-time-intervals-in-postgres/50264875?noredirect=1#comment87571181_50264875,后来在问题中再次更新以包含这些列mac and loc。我假设你想要每个单独的平均值(mac, loc).

date and time仍然是单独的列,vin* 列是类型float,并排除没有行的时间段:

更新后的查询还移动了设置返回函数generate_series() to the FROM列表,在 Postgres 10 之前更清晰:

SELECT t.mac, sn.sn, t.loc, ts.ts::time AS time, ts.ts::date AS date
     , t.vin1_av, t.vin2_av, t.vin3_av
FROM  (SELECT text '4as11111111') sn(sn)  -- provide sn here once
CROSS  JOIN LATERAL (
   SELECT min(date+time) AS min_ts, max(date+time) AS max_ts
   FROM   tbl
   WHERE  sn = sn.sn
   AND    date+time >= '2018-01-01 0:0'   -- provide time frame here
   AND    date+time <  '2018-01-02 0:0'
   ) grid
CROSS  JOIN LATERAL generate_series(min_ts, max_ts, interval '5 min') ts(ts)
CROSS  JOIN LATERAL (
   SELECT mac, loc
        , round(avg(vin1)::numeric, 2) AS vin1_av  -- cast to numeric for round()
        , round(avg(vin2)::numeric, 2) AS vin2_av  -- but rounding is optional
        , round(avg(vin3)::numeric, 2) AS vin3_av
   FROM   tbl
   WHERE  sn = sn.sn
   AND    date+time >= ts.ts
   AND    date+time <  ts.ts + interval '5 min'
   GROUP  BY mac, loc
   HAVING count(*) > 0  -- exclude empty slots
   ) t;

创建一个多列表达式索引来支持这一点:

CRATE INDEX bar_idx ON tbl (sn, (date+time));

数据库小提琴

但我更愿意使用timestamp一直。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Postgres 中获取时间间隔的平均值 的相关文章

  • 如何在Django项目中使用PostgreSQL的存储过程或函数

    我正在开发一个 Django 项目 我决定在 PostgreSQL 中编写逻辑代码 而不是用 Python 编写 因此 我在 PostgreSQL 中创建了一个存储过程 例如 存储过程如下所示 create or replace proce
  • 带有可变 WHERE 子句的批量 UPDATE 表

    我有一堆值对 foo1 bar1 foo2 bar2 我想做一堆更新 将 foo 列设置为 foo1 其中 bar 列为 bar1 我正在使用 psycopg2 在 Python 中执行此操作 我可以executemany与查询UPDATE
  • 更好地理解 SQL Server 中的架构

    就像标题一样 我还是一个SQLServer菜鸟 当我创建表 Mytable 时 数据库中显示 dbo Mytable 但有人能让我更好地理解模式吗 另外 在 Server 2008 TSQL 一书中 Itzik 说 在你的数据库中 表属于模
  • 如何拥有引用另一个表的检查约束?

    我在 SQL Server 2008 数据库中有以下表 tblItem 其中有一个ItemID field 好项目 它还有一个 ItemID 字段 并且有一个指向 tblItem 的外键 tblBadItem 它也有一个 ItemID 字段
  • 如何加速spark df.write jdbc到postgres数据库?

    我是 Spark 新手 正在尝试使用 df write 加速将数据帧的内容 可以有 200k 到 2M 行 附加到 postgres 数据库 df write format jdbc options url psql url spark d
  • SQL - 需要查找重复记录但排除反向事务

    我有一张交易表 偶尔会有 重复条目 如果 当管理员发现这些重复条目时 他们将撤销交易 从而创建负值 但由于监管要求 原始重复条目仍然保留 我想创建一个 SQL 查询 并使用 Crystal Reports 来制作报告 以便管理员轻松查找重复
  • IIF(...) 不是公认的内置函数

    我正在尝试在 Microsoft SQL Server 2008 R2 中使用它 SET SomeVar SomeOtherVar IIF SomeBool value when true value when false 但我收到一个错误
  • 使用连接池后如何处理过多的并发连接?

    Scenario 假设您有一个拥有大量流量的网站或应用程序 即使使用数据库连接池 性能也会受到真正的打击 站点 应用程序甚至可能崩溃 因为并发连接太多 Question 人们有什么选择来处理这个问题 我的想法 我在想有这个问题的人可以创建多
  • 如何使用原始 SQL 查询实现搜索功能

    我正在创建一个由 CS50 的网络系列指导的应用程序 这要求我仅使用原始 SQL 查询而不是 ORM 我正在尝试创建一个搜索功能 用户可以在其中查找存储在数据库中的书籍列表 我希望他们能够查询 书籍 表中的 ISBN 标题 作者列 目前 它
  • Django 模型:默认日期时间未转换为 SQL CURRENT_TIMESTAMP

    我正在使用 Django 模型创建 PostgreSQL DB 我有一个 DateTimeField 我想将当前时间戳设置为默认值 我知道有多个消息来源建议如何做到这一点 但是 当我在 Django 之外检查数据库时 默认时间戳不会显示 我
  • 在Oracle中使用IW和MM

    我使用 IW 表示每周结果 使用 MM 表示每月结果 但我总是收到错误 ORA 00979 not a GROUP BY expression 00979 00000 not a GROUP BY expression 我的疑问是这些 We
  • Pandas 中的 Groupby、转置和追加?

    我有一个数据框 如下所示 每个用户有10条记录 现在 我想创建一个如下所示的数据框 userid name1 name2 name10 这意味着我需要反转该列的每 10 条记录name并附加到新的数据框 那么 它是如何做到的呢 有什么办法可
  • ORA-12728: 正则表达式中的范围无效

    我想检查表中是否插入了有效的电话号码 所以我的触发代码在这里 select start index into mob index from gmarg mobile operators where START INDEX substr ne
  • postgresql 不同的不工作

    我使用以下代码从数据库获取值 但是当我编写这段代码时 测试看看问题出在哪里 我注意到查询没有从数据库中获取不同的值 这是查询 select distinct ca id as id acc name as accName pIsu name
  • 将DataTable批量插入postgreSQL表中

    在 SQL 中 我们执行类似的操作来批量插入数据表 SqlBulkCopy copy new SqlBulkCopy sqlCon copy DestinationTableName strDestinationTable copy Wri
  • 如果 Oracle SQL 中存在视图,则删除视图[重复]

    这个问题在这里已经有答案了 我是 Oracle 数据库系统的新手 Oracle 12c 中以下 SQL 语句的等效项是什么 DROP VIEW IF EXIST
  • 如何使用一个命令删除 SQL 数据库中的所有索引?

    那么 如何通过一条命令删除 SQL 数据库中的所有索引呢 我有这个命令可以获取所有 20 个左右的 drop 语句 但是如何从这个 结果集 运行所有这些 drop 语句呢 select from vw drop idnex 给我相同列表的另
  • SQL Server 中的 FIFO 查询

    我正在构建一个库存管理应用程序c with SQL server 我想做一个FIFO从我的表查询 我以可变价格购买了相同的产品 之后我卖掉了其中一些 我想根据 先进先出 进行查询BatchDate柱子 所以我想通过PurchasePrice
  • 更改表添加列并在同一条件 IF 语句中更新新列

    我正在尝试添加列并在同一 if 语句中更新它 BEGIN TRAN IF NOT EXISTS SELECT 1 FROM sys columns WHERE Name N Code AND Object ID Object ID N Te
  • 如何按 pandas 中的值对系列进行分组?

    我现在有一只熊猫Series与数据类型Timestamp 我想按日期对其进行分组 并且每组中有许多行具有不同的时间 看似显而易见的方法类似于 grouped s groupby lambda x x date 然而 熊猫的groupby按索

随机推荐