这里可以有几种解决方案,我想描述一个,我希望您可以根据您的特定需求使用/调整/扩展它(注意:我使用的是 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);
注意:对于 ms sql,您可以尝试with
语法,您将能够将这些插入/更新作为一个查询进行
4之后,您将拥有(基于问题的数据):
2013-10-30 07:01:23 1 1
2013-10-30 08:01:23 1 2
2013-10-30 09:01:23 1 3
2013-10-30 09:01:24 1 4
2013-10-30 16:12:03 -1 3
2013-10-30 17:02:03 -1 2
2013-10-30 17:12:03 -1 1
2013-10-30 18:12:03 -1 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;
所以,基本上说 - 除了您的范围之外,您还需要在期间开始之前获取最后一行,以了解在范围开始时有多少用户
5现在,你要计算平均值。平均是一个棘手的功能,取决于您的理解 - 可能会有不同的结果,平均用户每秒或平均工作量
这是区别:
100 users logged in at 09:00
98 users logged out at 09:01
1 user logged out at 09:02
Selection range: 09:00 - 09:59 (inclusive)
平均每分钟将是每分钟所有登录用户的总和除以 60
(100 + 2 + 1 + 57*1)/60 = 2.6(6) user per minute
但平均工作量可以计算为 (max(logged_users)+min(logged_users)) / 2
(100 + 1)/2 = 50.5 users, this is average simultaneous users logged in system
可以通过 SQL avg (sum(values)/count(values)) 计算另一个平均值,这将为我们提供
(100+98+1)/3 = 66.3(3) - another average workload in persons
第一个公式对我们说它同时只有2.65 个用户,但第二个显示“神圣的 #*&#@#@,它同时是 50.5 个用户”
另一个例子:
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)
第一个公式会给你(100*58 + 2 + 1)/60 = 96.71(6)
用户,第二个会继续给50.5
,第三个仍然66.3(3)
什么平均值最适合您?
要计算第一个平均值,您需要创建stored procedure
它将获取每分钟/秒的数据并在除法后总结它
要计算第二个变量:只需选择min/max
并除以 2
第三种变体:使用avg
而不是 max
注意#1:当然,所有这些方法都非常缓慢,流量很大,所以我建议您准备一些“预先计算”的表格,其中包含可以快速获取的数据(例如,您可以拥有每小时的数据,例如YYYY-MM-DD HH loggedInatStart, min, avg, median, max, loggedInatEnd
:)
注意#2:有时中位数平均值对于统计目的更有趣,要获得它,您将:每分钟计算有多少用户登录,选择不同的值,从此列表中选择中间值(对于我的示例,这将给我们 2 和2),或选择所有值,选择中间一个(对于我的示例,它将给我们 1 和 99)