查询从会话表中获取高峰时段

Posted

技术标签:

【中文标题】查询从会话表中获取高峰时段【英文标题】:Query to get peak hours from session table 【发布时间】:2012-03-07 11:12:07 【问题描述】:

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

我能否通过一次查询来确定一天中每小时有多少用户在线(即有多少会话有startTime <= hour AND endTime > hour)? 我想显示过去 2 个月的平均值,但如果这不可能,我可以使用 1 天的查询来管理并在脚本中计算平均值。

示例结果:

Hour    Online
00:00   10
01:00   12
02:00   10
....
16:00   100
17:00   120
....

(小时也可以是一个简单的整数,没关系)

数据库是 mysql 5。

【问题讨论】:

同一查询中的每小时在线用户数和月平均数?那不会飞:) 您能否提供一个示例结果集,其中包含您需要的所有列。 @Tobsey 添加。如您所见,没有什么特别的(结果,查询可能) 会话可以在午夜运行 - 例如。 2011 年 3 月 5 日 23:30 开始,2011 年 3 月 6 日 00:30 结束? @MarkBannister 是的。从理论上讲,它们可以持续数天,尽管我怀疑是否有人在实践中已经在线这么长时间了。 【参考方案1】:

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

这里的主要问题是一种构建一天中小时表的方法。在 mysql 中没有递归选择能力迫使我通过联合创建一个表。如果我们可以接受在该日期没有人登录的缺失日期,则日期会更容易。如果没有,可以使用与小时类似的技巧来延长日期,例如延长 7 天。 交叉连接将生成一个日期表,每个日期都有一天的 24 小时。现在我们需要计算此时处于活动状态的会话。为此,我们需要将 startTime 截断为小时边界,并将交叉连接组合时间放在截断的 startTime 和 endTime 内(不需要截断)。我们的数据终于来了。

要获得过去两个月的平均值,只需将此选择包装在另一个分组小时中并计算 avg(Users)。如果您确实必须使用单个查询来返回两个数据集,则可以将此查询与平均查询合并,其中平均查询将返回 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

【讨论】:

不太好用,但我设法用它构建了一些东西(见我的回答)【参考方案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

【讨论】:

以上是关于查询从会话表中获取高峰时段的主要内容,如果未能解决你的问题,请参考以下文章

mysql查询之 用户行程的取消率,人流量高峰时段

SQL 查询买卖高峰时间段

对80/20原则的理解

线上线下流量趋势

高并发系统建设经验总结

性能需求调研与分析的方法