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

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

4

1 回答 1

0

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

这个想法是将数据分解为登录和注销。注销发生在登录后的登录 + secs 秒,因此很容易计算。每个登录都获得一个值+1(将并发用户计数加一)。每次注销都会获得一个值-1

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

最后一步是计算平均值。这需要考虑持续时间才能准确。但是,这并不是 100% 准确的,因为它会在没有登录的情况下错过开头和结尾的句点。为此,您可能需要向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,很容易将其合并以找出接下来会发生什么,而不是使用时间。

于 2013-04-30T15:01:10.317 回答