并发用户仪表板

时间:2013-04-30 14:40:09

标签: python sql sql-server

我有一个用户访问日志表到应用程序。以下是一些示例数据:

userid    |          login          | duration (seconds)
--------------------------------------------------------
1         | 2013-04-30 09:24:07.127 | 21456     
2         | 2013-04-29 09:22:05.023 | 26477     
1         | 2013-04-30 10:24:07.787 | 86543    
2         | 2013-04-30 12:55:55.846 | 32237    
1         | 2013-04-30 08:24:12.347 | 92231     

我的目标是从这些数据中获取一些指标。我需要捕获过去一周内登录用户的最小,最大和平均并发数。除非有人有更好的想法,否则我相信会得到一个有意义的并发连接平均值,我需要选择一个间隔。如果我错了,请纠正我。如果是这样,我认为我不应该遇到麻烦。它的最小值和最大值给我带来了麻烦。我试图在sql中这样做,但无济于事。问题在于试图如何衡量连接之间的重叠。我应该把它拉出来并在python中完成。我会有超过10万行,所以它可能会有点麻烦,但我只需要每天生成一次报告,因此效率不是我最关心的问题。

对不起,我没有任何示例代码,我真的不知道如何从这里开始。谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

这是应该有所帮助的。例如,您可能需要努力弄清楚如何处理周边界。

我们的想法是将数据分解为登录和注销。注销在登录后的登录+秒秒发生,因此可以轻松计算。每次登录都会获得+1的值(将并发用户数加1)。每次注销都会获得-1的值。

此版本的查询使用相关子查询来确定并发用户数和下一个事件的时间。在SQL Server 2012中,这些可以由累积总和(sum() over (partition . . order by)lead()替换。

最后一步是计算平均值。这需要考虑持续时间是否准确。但是,这不是100%准确,因为它会在开始和结束时错过句点而没有登录。为此,您可能需要向事件CTE:

添加值为0的虚假记录
with d as (
        select 1 as userid, CAST('2013-04-30 09:24:07.127' as datetime) as logint, 21456 as secs union all
        select 2, CAST('2013-04-29 09:22:05.023' as datetime), 26477 union all
        select 1 , CAST('2013-04-30 10:24:07.787' as datetime), 86543 union all
        select 2, CAST('2013-04-30 12:55:55.846' as datetime), 32237 union all
        select 1, CAST('2013-04-30 08:24:12.347' as datetime), 92231
     ),
     events as (
      select logint as thetime, 1 as loginp
      from d
      union all
      select DATEADD(second, secs, logint), -1
      from d
     ),
     t as (
      select e.*,
             (select SUM(loginp) from events e2 where e2.thetime <= e.thetime) as concurrents,
             (select top 1 thetime from events e2 where e2.thetime > e.thetime order by e2.thetime desc) as nexttime,
             DATEDIFF(second, thetime, (select top 1 thetime from events e2 where e2.thetime > e.thetime order by e2.thetime desc)) as dur
      from events e
     )
select SUM(concurrents*1.0*dur)/SUM(dur) as avg_concurrents,
       MIN(concurrents), MAX(concurrents)
from t

这假设没有重复次数 - 您无法区分问题中的重复项。如果您有一个id,那么很容易将其合并以确定接下来会发生什么,而不是使用时间。