Mysql 从会话表中获取高峰小时数的查询

Mysql 从会话表中获取高峰小时数的查询,mysql,sql,aggregate-functions,Mysql,Sql,Aggregate Functions,我有一个包含用户会话的表,即用户登录我的应用程序的时间段。每个会话都有一个开始和结束时间戳 通过一个查询,我可以确定一天中每小时有多少用户在线,即开始时有多少会话? 我想显示过去两个月的平均值,但如果这不可能,我可以使用一个查询进行管理,该查询只执行一天,并在脚本中计算平均值 样本结果: Hour Online 00:00 10 01:00 12 02:00 10 .... 16:00 100 17:00 120 .... 小时也可能是一个简单的整数,没什么大不了的

我有一个包含用户会话的表,即用户登录我的应用程序的时间段。每个会话都有一个开始和结束时间戳

通过一个查询,我可以确定一天中每小时有多少用户在线,即开始时有多少会话? 我想显示过去两个月的平均值,但如果这不可能,我可以使用一个查询进行管理,该查询只执行一天,并在脚本中计算平均值

样本结果:

Hour    Online
00:00   10
01:00   12
02:00   10
....
16:00   100
17:00   120
....
小时也可能是一个简单的整数,没什么大不了的


数据库是MySQL 5。

我一直在等待其他人的介入,因为我对MySQL并不精通,我相信一定有更好的解决方案

这里的主要问题是如何构建一天中的小时表。mysql中没有递归选择功能,这迫使我通过union创建一个表。如果我们可以接受没有人在该日期登录时丢失的天数,那么日期就更容易了。如果不是,可以使用与小时类似的技巧来延长日期,例如七天。 交叉联接将生成一个日期表,每个日期都有一天的所有24小时。现在我们需要统计此时处于活动状态的会话。要做到这一点,我们需要截断startTime到hour的边界,并将交叉连接组合时间放在截断的startTime和endTime中,这两个时间不需要截断。我们的数据终于到了

若要获得过去两个月的平均值,只需将此选择再包装一小时,然后计算平均值。若您确实必须有一个查询来返回这两个数据集,那个么您可以将此查询与average查询合并,average查询将为date返回null

附加免责声明:如前所述,我不知道MySql。我尝试使用在线手册编写日期和时间转换函数。也许失败得很惨,但我相信你会纠正我的。我也不确定保留的关键字

select days.date, 
hour,
count (s.startTime) Users
from
(
    (
        select 0 hour
        union
        select 1 hour
        union
        select 2 hour
        union
        select 3 hour
        union
        select 4 hour
        union
        select 5 hour
        union
        select 6 hour
        union
        select 7 hour
        union
        select 8 hour
        union
        select 9 hour
        union
        select 10 hour
        union
        select 11 hour
        union
        select 12 hour
        union
        select 13 hour
        union
        select 14 hour
        union
        select 15 hour
        union
        select 16 hour
        union
        select 17 hour
        union
        select 18 hour
        union
        select 19 hour
        union
        select 20 hour
        union
        select 21 hour
        union
        select 22 hour
        union
        select 23 hour
    ) hours
    cross join
    (
    --  We need date portion only
        select distinct date(startTime) date from s 
        union select distinct date(endTime) from s
    ) days
)
left join s
-- date+hour, hopefully
   on date_add(date, interval hour HOUR) 
   -- startTime is truncated to hour, hopefully
      between date_sub(s.startTime interval minutes(s.startTime) MINUTE) 
      and s.endTime
-- last two months
where days.date between date_sub (now() interval 2 MONTH) and now()
group by days.date, hour
order by 1, 2

我一直在等待其他人的介入,因为我不精通mysql,我相信一定有更好的解决方案

这里的主要问题是如何构建一天中的小时表。mysql中没有递归选择功能,这迫使我通过union创建一个表。如果我们可以接受没有人在该日期登录时丢失的天数,那么日期就更容易了。如果不是,可以使用与小时类似的技巧来延长日期,例如七天。 交叉联接将生成一个日期表,每个日期都有一天的所有24小时。现在我们需要统计此时处于活动状态的会话。要做到这一点,我们需要截断startTime到hour的边界,并将交叉连接组合时间放在截断的startTime和endTime中,这两个时间不需要截断。我们的数据终于到了

若要获得过去两个月的平均值,只需将此选择再包装一小时,然后计算平均值。若您确实必须有一个查询来返回这两个数据集,那个么您可以将此查询与average查询合并,average查询将为date返回null

附加免责声明:如前所述,我不知道MySql。我尝试使用在线手册编写日期和时间转换函数。也许失败得很惨,但我相信你会纠正我的。我也不确定保留的关键字

select days.date, 
hour,
count (s.startTime) Users
from
(
    (
        select 0 hour
        union
        select 1 hour
        union
        select 2 hour
        union
        select 3 hour
        union
        select 4 hour
        union
        select 5 hour
        union
        select 6 hour
        union
        select 7 hour
        union
        select 8 hour
        union
        select 9 hour
        union
        select 10 hour
        union
        select 11 hour
        union
        select 12 hour
        union
        select 13 hour
        union
        select 14 hour
        union
        select 15 hour
        union
        select 16 hour
        union
        select 17 hour
        union
        select 18 hour
        union
        select 19 hour
        union
        select 20 hour
        union
        select 21 hour
        union
        select 22 hour
        union
        select 23 hour
    ) hours
    cross join
    (
    --  We need date portion only
        select distinct date(startTime) date from s 
        union select distinct date(endTime) from s
    ) days
)
left join s
-- date+hour, hopefully
   on date_add(date, interval hour HOUR) 
   -- startTime is truncated to hour, hopefully
      between date_sub(s.startTime interval minutes(s.startTime) MINUTE) 
      and s.endTime
-- last two months
where days.date between date_sub (now() interval 2 MONTH) and now()
group by days.date, hour
order by 1, 2

我无法让Nikola的查询正常工作,但是使用了其中的一些技术来创建这个查询,它可以得到整个期间每小时的平均值,这已经足够好了

SELECT hour, AVG(dayHourCount) FROM 

(
SELECT hour, day, dayHour, COUNT(*) AS dayHourCount FROM
(
SELECT hour, day, day + INTERVAL hour HOUR AS dayHour FROM
    (
        select 0 AS hour
        union
        select 1 AS hour
        union
        select 2 AS hour
        union
        select 3 AS hour
        union
        select 4 AS hour
        union
        select 5 AS hour
        union
        select 6 AS hour
        union
        select 7 AS hour
        union
        select 8 AS hour
        union
        select 9 AS hour
        union
        select 10 AS hour
        union
        select 11 AS hour
        union
        select 12 AS hour
        union
        select 13 AS hour
        union
        select 14 AS hour
        union
        select 15 AS hour
        union
        select 16 AS hour
        union
        select 17 AS hour
        union
        select 18 AS hour
        union
        select 19 AS hour
        union
        select 20 AS hour
        union
        select 21 AS hour
        union
        select 22 AS hour
        union
        select 23 AS hour
    ) AS hours

INNER JOIN (SELECT DISTINCT DATE(start) AS day FROM PlayerSession ds WHERE ds.start > NOW() - INTERVAL 1 MONTH) AS days
) AS dayHours

LEFT JOIN PlayerSession s ON (s.start < dayHour AND s.lastActivity > dayHour)
LEFT JOIN Player p ON (s.player_id = p.id)

GROUP BY dayHour

) AS perDayHour

GROUP BY hour

我无法让Nikola的查询正常工作,但是使用了其中的一些技术来创建这个查询,它可以得到整个期间每小时的平均值,这已经足够好了

SELECT hour, AVG(dayHourCount) FROM 

(
SELECT hour, day, dayHour, COUNT(*) AS dayHourCount FROM
(
SELECT hour, day, day + INTERVAL hour HOUR AS dayHour FROM
    (
        select 0 AS hour
        union
        select 1 AS hour
        union
        select 2 AS hour
        union
        select 3 AS hour
        union
        select 4 AS hour
        union
        select 5 AS hour
        union
        select 6 AS hour
        union
        select 7 AS hour
        union
        select 8 AS hour
        union
        select 9 AS hour
        union
        select 10 AS hour
        union
        select 11 AS hour
        union
        select 12 AS hour
        union
        select 13 AS hour
        union
        select 14 AS hour
        union
        select 15 AS hour
        union
        select 16 AS hour
        union
        select 17 AS hour
        union
        select 18 AS hour
        union
        select 19 AS hour
        union
        select 20 AS hour
        union
        select 21 AS hour
        union
        select 22 AS hour
        union
        select 23 AS hour
    ) AS hours

INNER JOIN (SELECT DISTINCT DATE(start) AS day FROM PlayerSession ds WHERE ds.start > NOW() - INTERVAL 1 MONTH) AS days
) AS dayHours

LEFT JOIN PlayerSession s ON (s.start < dayHour AND s.lastActivity > dayHour)
LEFT JOIN Player p ON (s.player_id = p.id)

GROUP BY dayHour

) AS perDayHour

GROUP BY hour

同一查询中的每小时在线用户数和月平均数?“这是行不通的:你能给出一个示例结果集,给出你需要的所有列吗?”托比补充道。正如你所看到的,结果没有什么特别之处,查询可能会在午夜运行-例如,2011年3月5日23:30开始,2011年3月6日00:30结束?@MarkBannister是的。理论上,他们可能会持续好几天,但我怀疑在实践中是否有人在线这么长时间。在同一个查询中,每小时在线用户数和每月平均数?“这是行不通的:你能给出一个示例结果集,给出你需要的所有列吗?”托比补充道。正如你所看到的,结果没有什么特别之处,查询可能会在午夜运行-例如,2011年3月5日23:30开始,2011年3月6日00:30结束?@MarkBannister是的。理论上,它们可能会持续几天,尽管我怀疑有人在实践中已经在线这么长时间了。不太有效,但我设法用它构建了一些东西。我的回答不太有效,但我设法用它构建了一些东西。看到我的答案了吗