关于 sql:对每个时间间隔的事件进行分组和计数,加上运行总数

Group and count events per time intervals, plus running total

我是一个相当新的 Postgres 用户,我确信已经有了答案,但我找不到。
我需要分析活动日志表中的一些数据,按时间段对结果进行分组。

这个问题的一个简单版本是一个包含三个字段的表:

1
2
3
4
5
    COLUMN    |           TYPE           |              Modifiers
--------------+--------------------------+-------------------------------------
 period_start | TIMESTAMP WITH TIME zone | NOT NULL
 user_id      | text                     | NOT NULL
 action       | text                     | NOT NULL

我想要捕获的操作字符串可能是"create_entry"(是的,我知道这很糟糕,但我坚持使用它)

我正在寻找的输出是按年和月显示"create_entry"操作计数的报告。类似于:

1
2
3
4
5
 YEAR | MONTH | Entries
------+-------+----------
 2013 |  12   | 14345
 2014 |   1   | 9876
 2014 |   2   | 10234

我的直觉是用子查询来解决这个问题,但环顾四周似乎暗示循环可能是要走的路。

不管怎样,我已经超出了我的深度,正在寻找正确的方向。

编辑

根据我输入此内容时收到的请求提出的补充问题.. 上面的一个变体将显示逐月累积的总数(尽管我想我可以自己根据关于上述方法 - 我只是添加它以防它与方法相关)。


使用 date_trunc() 将时间戳截断为月份,并在单个列中涵盖年份和月份。您可以使用 to_char() 以任何您喜欢的方式对其进行格式化。

要获得您在补充问题中提到的运行计数,请添加窗口函数:

1
2
3
4
5
6
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);

用于 Psotgres 9.6 的 sqlfiddle
db<>fiddle here for Postgres 12

窗口函数在聚合函数之后执行,因此我们可以在同一查询级别的聚合上运行窗口函数。相关:

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

必须在窗口函数和 GROUP BY 中使用相同的基本表达式:date_trunc('month', period_start).


如果我理解正确,您只想 GROUP BY 表中的年份和月份,对于具有 actioncreate_entry 的每一行:

1
2
3
4
5
6
7
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 小提琴