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

Sql 按时间间隔分组和计数事件,加上运行总数,sql,postgresql,loops,aggregate-functions,window-functions,Sql,Postgresql,Loops,Aggregate Functions,Window Functions,我是一个新的Postgres用户,我确信已经有了答案,但我找不到答案。 我需要分析活动日志表中的一些数据,按时间段对结果进行分组 该问题的一个简单版本是一个包含三个字段的表: Column | Type | Modifiers --------------+--------------------------+------------------------------------- period_start |

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

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

    Column    |           Type           |              Modifiers
--------------+--------------------------+-------------------------------------
 period_start | timestamp with time zone | not null
 user_id      | text                     | not null
 action       | text                     | not null
我想要捕获的动作字符串可以是“create_entry”(是的,我知道这和db设计一样糟糕,但我一直坚持这样做)

我要查找的输出是一个报告,其中显示了“创建条目”操作的年度和月度计数。比如:

 Year | Month | Entries
------+-------+----------
 2013 |  12   | 14345
 2014 |   1   | 9876
 2014 |   2   | 10234
我的本能是用子查询来解决这个问题,但环顾四周,似乎有一种建议认为循环可能是解决问题的方法

无论哪种方式,我都不在我的能力范围之内,正在寻找一个正确的方向

编辑


这是一个补充问题,是根据我打字时收到的请求提出的。。上面的一个变化将显示一个月一个月的累计总数(尽管我想我可以根据上面的方法自己计算出来-我只是添加了这个,以防它与方法相关)。

如果我理解正确,您只需要按照表中的年和月进行分组,对于具有
创建项的
操作的每一行

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;

用于截断月份的时间戳,并在单个列中覆盖年份和月份。您可以使用
to_char()

要获得您在补充问题中提到的跑步次数,请添加:

对于Psotgres 9.6
D博士后小提琴12

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


在window函数和GROUP BY中使用相同的基本表达式是很重要的:
date\u trunc('month',period\u start)

这就是为什么我喜欢StackOverflow-date\u PART和date\u trunc-我以前从未见过它们-我不确定它们之间是否有任何区别@欧文会知道的,他比我更专业
DATE\u PART
返回一个数字(2013、2等),并且
DATE\u TRUNC
返回一个时间戳,截断为该部分。所以,我的方式看起来更像你的示例输出。有时我讨厌选择一个首选答案。。。都很好,都是+1'd。我没有资格说哪一个是“最好的”,我怀疑它可能是@Erwin的,但我选择这一个是因为它是我实际使用的解决方案。@PerryW:我提出了
date\u trunc()
,偏离了您提出的结果格式,因为在一列上聚合比在两列上聚合便宜。不过,最有趣的是运行计数,它只需要一个查询级别。
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);