sql - 按时间间隔对事件进行分组和计数,以及运行总计

标签 sql postgresql loops aggregate-functions window-functions

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

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

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

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

我正在寻找的输出是一份按年份和月份显示“create_entry”操作计数的报告。像这样的东西:

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

我的本​​能是用子查询来解决这个问题,但环顾四周似乎有人建议循环可能是可行的方法。

无论哪种方式,我都超出了我的能力范围,正在寻找正确方向的插入力。

编辑

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

最佳答案

使用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);

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

必须在窗口函数和 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()。您需要显示本地时间单位,因此AT TIME ZONE更好。

fiddle
<子>旧sqlfiddle

关于sql - 按时间间隔对事件进行分组和计数,以及运行总计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22055461/

相关文章:

loops - s3-dist-cp 和 hadoop distcp 作业在 EMR 中无限循环

jquery - 为什么这个 Javascript (jQuery) 不会进入无限循环?

sql - 查找具有特定帖子 SQL 的所有男性用户

sql - 如何在 Postgresql 中将 LIKE 与 ANY 一起使用?

Postgresql Autodoc 安装 : "No rule to make target ` postgresql_autodoc. 1.in', `postgresql_autodoc.1' 需要。停止

php - Postgresql自定义函数返回表

java - Hibernate <generator> 混淆

r - 循环遍历数据框的列以使用 ggplot2 创建图

sql - Red Gate 的 sql 比较时出现错误 "commandtext property has not been initialized"

sql - 序列 ALTER RESTART 不会影响序列的当前值