2013-04-30 157 views
0

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

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中做到这一点。我会有100,000多行,所以它可能会有点麻烦,但我只需要每天生成一次报告,所以效率并不是我最关心的问题。

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

+0

如果你想做一段时间然后[this](http://stackoverflow.com/questions/12428873/avoiding-gaps-in-datetime-intervals-with-cte-and-start- and-end-datetimes/12504291#12504291)可能会有所帮助。尽管您可以总结所有时间的数据,但是它在数据库超过几年之后真的有意义吗? – HABO 2013-04-30 14:49:53

+0

我只需要捕获一周或更新的数据。 – Hoopdady 2013-04-30 15:11:42

+0

如果您正在尝试评估系统上的负载,我无法想象这些用户在登录后仍处于活动状态。 – JeffO 2013-04-30 15:45:54

回答

0

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

这个想法是将数据分解为登录和注销。登录发生在登录后的登录+秒秒以便轻松计算。每个登录名的值为+1(并发用户数加1)。每个注销的值都是-1

该版本的查询使用相关的子查询来计算并发用户的数量和到下一个事件的时间。在SQL Server 2012中,这些可以用累加和来代替(sum() over (partition . . order by)lead()

最后一步是计算平均值,这需要考虑持续时间的准确性。它会怀念在开始阶段并没有结束登录为此,你可能需要用的0到事件的值添加虚假记载CTE:

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,很容易就可以把它弄清楚下一步会发生什么,比使用时间。

+0

所以对我来说有点难以遵循一些逻辑,但是我很困惑你为什么要用'd'(选择......),然后你选择样本表中的每一行。知道表中的内容是什么,所以它很难将这些值插入到查询中,但是,我的表格也有100,000多行,我不想选择并联合所有这些值。你提出的建议是什么? – Hoopdady 2013-04-30 15:22:07

+0

@Hoopdady - 调试或理解这种类型的操作的一种方法是将最后一个'select'替换为显示中间结果的'select'。'select * from d'将显示您的样本数据。 'select * from events'显示它变成了登录表(+1)和退出表(-1)。 'select * from t'显示_的第一部分,然后出现一个奇迹。 – HABO 2013-04-30 19:39:40