我为人们提供了timestamps
和states
的表格。
|:--------------------------------------------------------------:|
| 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 |
我的挑战是,找出有多少用户
每个时间间隔同一时间MAX(logged on) AND AVG(logged on)
。我认为,当我看到有多少用户每秒同时登录时,我就会离开。
|:-------------------------------------:|
| timestamp | state | userid |
|:-------------------------------------:|
| 1383123683 | 1 | 4711 |
| 1383123684 | 1 | 4711 |
| 1383123684 | 1 | 4712 |
| 1383123685 | 1 | 4711 |
| 1383123685 | 1 | 4712 |
| ... | ... | ... |
顺便说一下,一个时间间隔是四分之一小时。
数据来自INSERT INTO
所以我的想法是创建一个触发器并在帮助表中写入每行一行(UNIX时间戳),在开始和结束之间添加state_id
。
最后,必须能够对秒进行分组并计算datasets
以查明一秒钟内存在多少行。对于AVG
我还没有公式:-)。你知道,这是一个时间问题。
但我不确定,如果我的想法很好,因为我担心我的计划需要大量的表现和空间。
更好的想法是,只写start-time
和end-time
,但我失去了分秒的可能性。
如果我的数据库中没有数千行,我该如何管理?
答案 0 :(得分:0)
这里可以有几个解决方案,我想描述一个,我希望你可以使用/自适应/扩展它以满足你的特定需求(注意:我使用的是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 totalsum colum:
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用户在同一时间,但第二个显示“圣#*&amp;#@#@,同时是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:有时median average对于统计目的来说更有趣,为了获得它,您将:每分钟计算登录的用户数,选择不同的值,从此列表中选择中间(对于我的示例)这将给我们2和2),或选择所有值,选择中间值(对于我的例子,它将给我们1和99)