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)