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