Postgres 每小时按数据分组,然后找到 max 和 min createdAt 的时间差并计算它们的总和

Posted

技术标签:

【中文标题】Postgres 每小时按数据分组,然后找到 max 和 min createdAt 的时间差并计算它们的总和【英文标题】:Postgres group by data hourly,then find the time difference from max and min createdAt and calculate their sum 【发布时间】:2021-04-01 15:37:14 【问题描述】:

我有一张这样的桌子:

p_id |      createdat      | pagetitle | sessionid |      text       | device  | deviceserial
------+---------------------+-----------+-----------+-----------------+---------+--------------
      | 2020-09-03 06:59:18 |           |           | Approve         | android | 636363636890
      | 2020-09-03 08:40:10 |           |           | launchComponent | Android | 636363636890
      | 2020-09-03 08:40:11 |           |           | hi              | Android | 6625839827
      | 2020-09-03 08:45:11 |           |           | hi              | Android | 6625839827
      | 2020-09-03 08:43:10 |           |           | launchComponent | Android | 636363636890
      | 2020-09-03 08:50:11 |           |           | hi              | Android | 6625839827
      | 2020-09-03 08:47:10 |           |           | launchComponent | Android | 636363636890
      | 2020-09-03 08:53:11 |           |           | hi              | Android | 6625839827
      | 2020-09-03 08:50:10 |           |           | launchComponent | Android | 636363636890
      | 2020-09-03 08:55:11 |           |           | hi              | Android | 6625839827
      | 2020-09-03 08:52:10 |           |           | launchComponent | Android | 636363636890
      | 2020-09-03 09:00:11 |           |           | hi              | Android | 6625839827
      | 2020-09-03 08:55:10 |           |           | launchComponent | Android | 636363636890
      | 2020-09-03 09:05:11 |           |           | hi              | Android | 6625839827
      | 2020-09-03 08:59:10 |           |           | launchComponent | Android | 636363636890
      | 2020-09-03 09:07:11 |           |           | hi              | Android | 6625839827
      | 2020-09-03 09:01:10 |           |           | launchComponent | Android | 636363636890
      | 2020-09-03 09:09:11 |           |           | hi              | Android | 6625839827
      | 2020-09-03 09:03:10 |           |           | launchComponent | Android | 636363636890
      | 2020-09-03 09:09:11 |           |           | hi              | Android | 6625839828
      | 2020-09-03 09:03:10 |           |           | launchComponent | Android | 636363636891
      | 2020-09-03 09:13:11 |           |           | hi              | Android | 6625839828

我想按数据每小时和设备序列进行分组。然后从每小时 createdAt 中找到最大值和最小值,然后计算总和。 这就是我尝试过的查询:

Select deviceserial,DATE_PART('minute', max(createdat)::timestamp - min(createdat)::timestamp) AS time_difference,date_part('hour', createdat) as hr FROM json_table2  GROUP BY deviceserial,hr;

这是我的结果:

deviceserial | time_difference | hr
--------------+-----------------+----
 636363636891 |               3 |  9
 6625839832   |               0 | 11
 636363636890 |               0 |  6
 636363636890 |              19 |  8
 6625839830   |               0 | 10
 6625839830   |               0 | 12
 6625839835   |               0 | 10
 6625839833   |               0 | 12
 6625839828   |               4 |  9
 6625839832   |               0 | 10
 6625839835   |               0 | 11
 636363636890 |               2 |  9
 6625839827   |               9 |  9
 6625839833   |               0 | 11
 6625839827   |              15 |  8

我想找到这样的东西。它将是每小时时间差的总和(createdAt 差异)groupby deviceserial:

deviceserial | time_difference | 
--------------+-----------------+----
 636363636890 |              21 |   
 6625839827   |              24 | 

And for other values as well...

这里我正在尝试查找不同deviceSerial的设备使用情况。

【问题讨论】:

嗨,也许对minmax 值使用子查询? 您想要一个小时内的最大值和最小值之差的总和?这对我来说真的没有意义。 @GordonLinoff,createdAt 是事件创建时的值。事件被添加到购物车,编辑等等。我试图找到每小时的设备使用量并将它们加在一起以找到总数设备的使用时间为 24 小时。所以我按 deviceSerial 和每小时对数据进行分组。我不知道这是查找设备使用情况的正确方法。 谢谢大家。我会再问一个问题。我会在那里解释,我想要实现什么。 【参考方案1】:

如果我正确地关注了您,那是您现有查询之上的另一个聚合级别:

select deviceserial, sum(time_difference) as time_difference
from (
    select deviceserial,
        date_part('minute', max(createdat)::timestamp - min(createdat)::timestamp) as time_difference,
        date_trunc('hour', createdat) as hr 
    from json_table2  
    group by deviceserial, hr
) t
group by deviceserial

我将查询更改为使用date_trunc() 而不是date_part():后者将不同日期同一时间发生的记录一起计算,我认为您不希望这样做。

虽然这可能会回答您的直接问题,但我想知道结果有多大用处。您可能想问另一个问题,从一开始就解释您要做什么。

【讨论】:

【参考方案2】:

使用第二级聚合。

SELECT deviceserial,
       sum(time_difference) time_difference
       FROM (SELECT deviceserial,
                    extract(epoch FROM max(createdat) - min(createdat)) time_difference,
                    FROM json_table2
                    GROUP BY deviceserial,
                             date_part('hour', createdat)) x
       GROUP BY deviceserial;

如果你想要间隔的长度以分钟为单位,而不仅仅是它的分钟部分,你最好使用extract() 而不是date_part()。 (即使两者都产生相同的结果here,因为最小值和最大值最多相隔一个小时。但如果你有一天选择将分组更改为例如按天,你会得到错误的结果,一开始可能根本不会注意到。)

如果createdat 已经是合适的类型,您可能不需要转换min()max()

【讨论】:

以上是关于Postgres 每小时按数据分组,然后找到 max 和 min createdAt 的时间差并计算它们的总和的主要内容,如果未能解决你的问题,请参考以下文章

Pandas 数据透视表和分组按月和小时

按数据区间分组

oracle按小时分组查询

每小时获取时间片,但按机器 ID 分组

按日期分组Java

时区感知 postgres 查询为分钟、小时、天创建时间序列