Sql 查找间隔内的最大登录次数

Sql 查找间隔内的最大登录次数,sql,tsql,sql-server-2012,Sql,Tsql,Sql Server 2012,我有一张有时间戳和状态的桌子 |:--------------------------------------------------------------:| | user_id | state | start_time | end_time | |:--------------------------------------------------------------:| | 4711 | 1 | 2013-10-30

我有一张有时间戳和状态的桌子

|:--------------------------------------------------------------:|
| user_id   |  state | start_time          | end_time            |
|:--------------------------------------------------------------:|
| 4711      |  1     | 2013-10-30 09:01:23 | 2013-10-30 17:12:03 |
| 4712      |  1     | 2013-10-30 07:01:23 | 2013-10-30 18:12:03 |
| 4713      |  1     | 2013-10-30 08:01:23 | 2013-10-30 16:12:03 |
| 4714      |  1     | 2013-10-30 09:01:24 | 2013-10-30 17:02:03 |
我的挑战是,找出有多少用户 每个间隔的MAXlogged on和Avgloged on时间相同。我想,当我看到每秒有多少用户同时登录时,我就会退出

|:-------------------------------------:|
| timestamp  |  state | userid          |
|:-------------------------------------:|
| 1383123683 |  1     | 4711            |
| 1383123684 |  1     | 4711            |
| 1383123684 |  1     | 4712            |
| 1383123685 |  1     | 4711            |
| 1383123685 |  1     | 4712            |
| ...        | ...    | ...             |
顺便说一下,每隔一刻就是一刻钟

数据是通过INSERT输入的,所以我的想法是将一个触发器装入一个helper表中,并在开始和结束之间的每秒钟UNIX时间戳中写入一行,添加state_id

最后,必须能够在几秒钟内对数据集进行分组和计数,以确定一秒钟内存在多少行。对于平均值,我还没有一个公式:-。你知道,这是个时间问题

但我不确定我的想法是否好,因为我担心我的计划需要大量的表现和空间

更好的办法是,只写开始时间和结束时间,但我失去了在几秒钟内分组的可能性


如果我的数据库中没有数千行,我如何管理它?

这里有几种解决方案,我想描述一种,我希望您可以根据您的特殊需要使用/adapt/extent。注意:我使用的是mysql方言,对于ms sql,它的语法可能有点不同,但这种方法可以工作:

1创建新表,其结构如下:

create table changelog (
changetime datetime,
changevalue int,
totalsum int,
primary key (changetime)
);
2插入基本数据:

insert into changelog
select changet, sum(cnts), 0
from
(
select start_time as changet, 1 as cnts from testlog
union all
select end_time as changet, -1 from testlog
) as q
group by changet;
3更新总计柱:

update changelog as a set totalsum = ifnull((select sum(changevalue) from (select changet, sum(cnts) as changevalue, 0
from
(
select start_time as changet, 1 as cnts from testlog
union all
select end_time as changet, -1 from testlog
) as q
group by changet) as b where b.changet<=a.changetime),0);
如您所见,max已在此处登录,但有一个问题,假设您需要为范围选择数据:08:00-08:01,表中没有数据,因此类似这样的查询将不起作用:

SELECT max(totalsum)
FROM changelog
where changetime between cast(@startrange as datetime) and cast(@endrange as datetime)
但您可以将其更改为:

SELECT max(totalsum)
from
(
select max(totalsum) as totalsum FROM changelog
where changetime between cast(@startrange as datetime) and cast(@endrange as datetime)
union all
select totalsum from changelog where changetime=(select max(changetime) from changelog where changetime<cast(@startrange as datetime))
) as q;
平均每分钟将是每分钟所有登录用户的总和除以60

(100 + 2 + 1 + 57*1)/60 = 2.6(6) user per minute
但平均工作负载可以计算为maxlogged_用户+minlogged_用户/2

(100 + 1)/2 = 50.5 users, this is average simultaneous users logged in system
另一个平均值可以通过SQL avg sumvalues/countvalues计算,这将为我们提供

(100+98+1)/3 = 66.3(3) - another average workload in persons
第一个公式告诉我们,它在同一时间只有2.65个用户,但第二个公式显示holy*&@,它在同一时间有50.5个用户

另一个例子:

第一个公式将给出100*58+2+1/60=96.716个用户,第二个公式将继续给出50.5个用户,第三个公式仍然是66.33个用户

一般来说,什么最适合你

要计算第一个平均值,您需要创建存储过程,该存储过程将获取周期中每分每秒的数据,并在除法后对其进行汇总

要计算第二个变量:只需选择最小值/最大值并除以2

第三种变体:使用平均值而不是最大值

注1:当然,所有这些方法都非常慢,流量巨大,因此我建议您准备一些预先计算的表格,其中包含可以快速获取的数据。例如,您可以获得每小时的数据,如:YYYY-MM-DD HH loggedInatStart、min、avg、median、max、loggedInatEnd


注2:有时出于统计目的更有趣,为了获得它,您将:计算每分钟有多少用户登录,选择不同的值,从列表中选择中间值作为我的示例,这将为我们提供2和2,或者选择所有值,选择中间的一个作为我的例子,它会给我们1和99,我不确定我是否理解这个短语顺便问一下,一个间隔是一刻钟,你的意思是开始时间和结束时间总是以:0:0:15:0:30:0 45:0结束吗?另一个问题-用户是否有可能有重叠的loggedin时间?间隔只是一个信息。应计算一段时间间隔的最大值。我认为这些信息对于解决方案来说并不重要。是的,用户可以有重叠的登录时间,正如我的示例所示,非常感谢您出色的代码和大量的行。它作为一个示例,我在mssql环境中对我的生产数据进行测试。我将在测试后发表评论。嗨,伊利亚,我努力用命令更新mssql中的表;具有但我失败了。我通过插入的伪表中的触发器获得一个数据集。你能不能给我一点提示,如何计算触发器的总和?Thanks@Frank在触发器中,您只需获取前一行,然后按id desc从tbl订单中选择top 1 totalsum,然后按1hi ilya进行inc或dec,谢谢您的快速回答。在触发器中设置变量会导致错误,因为返回的值超过1。我想这是错误的方式。你能帮我做这件事吗;作为一种选择。提前感谢-Frank@Frank这是不可能的,请选中“选择顶部1”-只能返回1个值
(100 + 1)/2 = 50.5 users, this is average simultaneous users logged in system
(100+98+1)/3 = 66.3(3) - another average workload in persons
100 users logged in at 09:00
99 users logged out at 09:58
1 user logged out at 09:59
Selection range: 09:00 - 09:59 (inclusive)