从开始和结束时间跨度得出的每分钟会话数

Posted

技术标签:

【中文标题】从开始和结束时间跨度得出的每分钟会话数【英文标题】:Count sessions per minute derived from start and end timespans 【发布时间】:2016-04-29 01:36:23 【问题描述】:

我有一个表格,其中包含用户活动的记录,这些记录涵盖了由开始时间和结束时间指示的跨度。我正在查找前一天中每单位时间在系统中活跃的用户数。

最大会话长度为一小时,并且不跨越小时界限。会话可以在同一分钟结束并开始新的会话。

这是查询的精简版:

with minutes AS (
    -- ignore this...it generates a day's worth of timestamps for each minute
    -- it's hairy but is what I'm stuck with on redshift
    select (dateadd(minute, -row_number() over (order by true), sysdate::date)) as minute
        from seed_table limit 1440
),
sessions as (
    select sid, ts_start, ts_end
    from user_sessions s
    where ts_end >= sysdate::date-'1 day'::interval 
        and ts_start < sysdate::date
)
select m.minute, count(distinct(s.sid))
from minutes m
left join sessions s on s.ts_end >= m.minute and s.ts_start < m.minute+'1 min'::interval
group by 1

我试图避免那个讨厌的左连接:

->  XN Nested Loop Left Join DS_BCAST_INNER  (cost=6913826151.95..4727012848741.55 rows=410434560 width=166)
    Join Filter: (("inner".ts_start < ("outer"."minute" + '00:01:00'::interval)) AND ("inner".ts_end >= "outer"."minute"))

根据 Gordon Linoff 的回答,这几乎对我有用。当用户的会话在一分钟内转换时,它计数不足。似乎是正确的方向。出于同样的原因,原始查询可能会过度计数,但获得一分钟不同会话 ID 计数的机会解决了这个问题。

select minute, sum(count) over (order by minute rows unbounded preceding) as users
from (
    select minute, sum(count) as count
    from (
        (
            select date_trunc('minute', ts_start) as minute, count(*) as count
            from sessions
            group by 1
        ) union all (
            select date_trunc('minute', ts_end) as minute, - count(*) as count
            from sessions
            group by 1
        )
    ) s1
    group by minute
) s2
order by minute;

为了比较,这里是一个小时的数据的计时结果:

    原始查询时间:81301.345 ms 求和查询时间:36242.342 毫秒

【问题讨论】:

【参考方案1】:

您可以通过计算每分钟开始和停止的次数,然后计算累积总和来更快地做到这一点。结果是这样的:

select minute, sum(cnt) over (order by minute)
from ((select date_trunc('minute', ts_start) as minute, count(*) as cnt
       from sessions
       group by 1
      ) union all
      (select date_trunc('minute', ts_end), - count(*)
       from sessions
       group by 1
      )
     ) s
group by minute
order by minute;

【讨论】:

差不多了。 Redshift 不会让我在外部范围内按分钟分组,因为窗口函数不是聚合函数。我将尝试用 sum-over 分别总结开始和结束,然后在外部范围内按分钟按常规聚合组求和。 我通过在计算滚动总和之前捕获每分钟的差异来使其工作。我得到的数字看起来正确。极好的!非常感谢! 还是不太对。这种方法的缺陷是当用户的会话结束并且新的会话在同一分钟内开始时,这在我的真实数据集中经常发生。这会导致少计。 @systemjack 。 . .嗯,您可能想用样本数据和所需结果提出另一个问题。这些边缘情况可能有点棘手。

以上是关于从开始和结束时间跨度得出的每分钟会话数的主要内容,如果未能解决你的问题,请参考以下文章

确定跨度的开始/结束时间

从日志中查找会话开始和结束信息

如何结束用户会话令牌并刷新令牌,时间超过 25 分钟

如何将 GridLayoutManager 中的项目固定为具有不同跨度计数的父项的开始和结束

ms-sql 如何查询开始时间与结束时间之间的数据?

使用 Pandas 的两个时间戳之间的每小时时间序列(以分钟为单位)