postgresql 按时间间隔对事件进行分组和计数,加上运行总数

jvlzgdj9  于 2023-08-04  发布在  PostgreSQL
关注(0)|答案(2)|浏览(174)

我是一个相当新的Postgres用户,我相信已经有一个答案,但我找不到它。
我需要分析活动日志表中的一些数据,按时间段对结果进行分组。
这个问题的一个简单版本是一个包含三个字段的表:

Column    |           Type           |              Modifiers
--------------+--------------------------+-------------------------------------
 period_start | timestamp with time zone | not null
 user_id      | text                     | not null
 action       | text                     | not null

字符串
我想捕获的动作字符串可以是'create_entry'(是的,我知道这是一个糟糕的数据库设计,但我坚持使用它)
我正在寻找的输出是一个报告显示计数的'创建_条目'行动的年和月。例如:

Year | Month | Entries
------+-------+----------
 2013 |  12   | 14345
 2014 |   1   | 9876
 2014 |   2   | 10234


我的直觉是用子查询来攻击这个问题,但环顾四周,似乎有一种建议,即循环可能是要走的路。
无论哪种方式,我超出了我的深度,并寻找一个推动正确的方向。

编辑

一个补充问题,基于一个请求,在我打这个..上面的一个变化,将显示一个月一个月的累计总数(尽管我想我可以自己根据上面的方法来计算出来--我只是在与方法相关的情况下添加这个)。

iqjalb3h

iqjalb3h1#

使用date_trunc()将时间戳截断为月份,并在一列中同时包含年和月。您可以使用to_char()以任何您喜欢的方式格式化它。
如要取得你在补充质询中提及的连续计数,请加上window function

SELECT to_char(date_trunc('month', period_start), 'Mon YYYY') AS month
     , count(*) AS month_ct
     , sum(count(*)) OVER (ORDER BY date_trunc('month', period_start)) AS running_ct
FROM   activity_log
WHERE  action = 'create_entry'
GROUP  BY date_trunc('month', period_start);

字符串
窗口函数是在聚合函数之后执行的,所以我们可以在同一查询级别的聚合上运行窗口函数。请参阅:

  • Postgres窗口函数和按异常分组

在窗口函数和GROUP BY中使用相同的基本表达式是很重要的:date_trunc('month', period_start)的值。
由于您在timestamptz上操作,因此通过截断到时区中的时间边界来修复时区可能出现的大小写问题。在我的示例中使用'Europe/Vienna'

SELECT to_char(date_trunc('month', period_start AT TIME ZONE 'Europe/Vienna'), 'Mon YYYY') AS month
     , COUNT(*) AS month_ct
     , sum(count(*)) OVER (ORDER BY date_trunc('month', period_start AT TIME ZONE 'Europe/Vienna')) AS running_ct
FROM   activity_log
WHERE  action = 'create_entry'
GROUP  BY date_trunc('month', period_start AT TIME ZONE 'Europe/Vienna');


从Postgres 12开始,我们也可以将时区作为第三个参数提供给date_trunc(),但这将返回timestamptz,这将导致to_char()的下一个角落问题。您需要显示 local 时间单位,因此AT TIME ZONE更好。
fiddle
老麻雀

fwzugrvs

fwzugrvs2#

如果我理解正确的话,你只需要对表中的年份和月份进行GROUP BY,对于每一行都有actioncreate_entry

SELECT
  DATE_PART('YEAR', period_start) as Year,
  DATE_PART('MONTH', period_start) as Month,
  COUNT(*) as Entries
FROM activity_log
WHERE action = 'create_entry'
GROUP BY Year, Month;

字符串
SQL小提琴

相关问题