postgresql 从一系列带时间戳的事件中获得洞察,例如平均会话持续时间

gmxoilav  于 2023-05-28  发布在  PostgreSQL
关注(0)|答案(1)|浏览(106)

我们有一组捕获并存储在Postgres数据库中的事件。为了简单起见,下面是一个示例:
| id|事件名|用户|事件日期时间|
| - -----|- -----|- -----|- -----|
| 一个|查看项目|鲍勃|2023-05-01 12:03|
| 2|访问主页|鲍勃|2023-05-01 12:12|
| 3|编辑配置文件|阿什利|2023-05-01 12:15|
| 4|查看项目|鲍勃|2023-05-01 12:25|
| 5个|查看项目|杰克|2023-05-01 12:26|
| 六|邀请用户|鲍勃|2023-05-01 12:28|
| 七个|执行搜索|杰克|2023-05-01 12:28|
| 八|提交票证|鲍勃|2023-05-01 12:29|
| 九个|执行搜索|鲍勃|2023-05-01 12:55|
| 十个|执行搜索|阿什利|2023-05-01 12:59|
基于这些事件,我们试图获得一些关于用户参与度的见解。具体来说,我们希望找出一个用户或一组用户的平均会话持续时间和平均会话数。出于我们的目的,我们将“会话”定义为用户执行操作的任何10分钟间隔。如果在一个特定的动作X之后,他们在10分钟或更长时间内没有执行另一个动作,我们认为动作X是该会话的最后一个动作,任何后续动作都是下一个会话的第一个动作,依此类推。
例如,基于上表,我们看到Bob在12:03查看了一个项目,然后9分钟后他访问了主页。但是他的下一个动作直到12:25才发生-所以基本上有一个会话超时。然后同样的事情发生在12点29分,之后他没有做任何事情,直到12点55分。所以在12:00到1:00的时间间隔里,他有三个不同的疗程,而杰克有一个,阿什利有两个。
根据上述条件,查询将返回什么:

  • 用户(或用户组)的平均会话持续时间
  • 平均会议次数
  • 每节课最常见的活动,例如由Jack和阿什利组成的小组在每个会话中执行了多少次“执行搜索”活动

这不是一个我们熟悉的主题,所以如果我们需要采取不同的策略(例如:创建另一个表/视图与这些派生的统计数据,然后查询),我很乐意红色更多关于这一点了。

dxpyg8gm

dxpyg8gm1#

使用cte在最后生成会话组和聚合:

with recursive cte(user_name, id, dt, c_id) as (
    select e.user_name, min(e.id), min(e.event_datetime), min(e.id) from events e 
    group by e.user_name
    union all
    select c.user_name, e.id, e.event_datetime, case when extract(epoch from e.event_datetime - c.dt) > 600 then e.id else c.c_id end 
    from cte c join events e on e.user_name = c.user_name and 
        e.event_datetime = (select min(e1.event_datetime) from events e1 where e1.user_name = c.user_name and e1.event_datetime > c.dt)
),
session_events as (
    select c.user_name, c.c_id, e.event_name, count(*) e_c from cte c join events e on e.event_datetime = c.dt group by c.user_name, c.c_id, e.event_name
)
-- average session duration for certain users (specified in parenthesis)
select avg(t1.av) av_session_sec 
from (select t.user_name, avg(extract(epoch from t.m2 - t.m1)) av 
      from (select c.user_name, c.c_id, min(c.dt) m1, max(c.dt) m2 
            from cte c group by c.user_name, c.c_id) t 
      where t.user_name in ('Jack', 'Ashley', 'Bob')
      group by t.user_name) t1
-- average number of sessions
select avg(t.s_c) av_sessions from (select c.user_name, count(distinct c.c_id) s_c 
   from cte c group by c.user_name) t
-- Most common activity per session per group
select t.*, e1.event_name from (select e.user_name, e.c_id, max(e.e_c) m from session_events e group by e.user_name, e.c_id) t
join session_events e1 on e1.user_name = t.user_name and e1.e_c = t.m
where t.user_name in ('Jack', 'Ashley')

See fiddle

相关问题