基于开始和结束时间的最活跃时间

Luc*_*eos 11 mysql

我正在记录我社区中游戏玩家的统计数据.对于他们在线和游戏中的状态,我在他们"开始"和"结束"时注册.为了显示当天最活跃的日期和小时,我想使用一个SQL语句,根据"开始"和"结束"日期时间值来衡量最活跃的时刻.

查看SQL - 从db中选择大多数"活动"时间我可以看到相似之处,但我还需要包括开始和结束时间之间的时刻.

也许最简单的方法是编写一个执行计算的cron,但我希望这个问题可能会教我如何在SQL中解决这个问题.

我一直在搜索一个SQL语句,它允许创建一个日期时间段并使用它来减去单个小时和几天.但无济于事.

---更新

我正在考虑更多这方面,我想知道根据一天中的每个小时(最活跃的小时)运行24个查询以及最活跃的一天的几个查询是否明智.但这似乎是对性能的浪费.但是这个解决方案可能会使查询成为可能:

SELECT COUNT(`userID`), DATE_FORMAT("%H",started) AS starthour, 
       DATE_FORMAT("%H",ended) AS endhour 
       FROM gameactivity 
       WHERE starthour >= $hour 
             AND endhour <= $hour GROUP BY `userID`
Run Code Online (Sandbox Code Playgroud)

(为了示例的目的,添加了$小时,当然我正在使用PDO.列也仅用于示例目的,无论您认为哪些都很容易用于解释,可以识别为开始和结束对我来说是好的)

附加信息; PHP 5.5 +,PDO,MySQL 5+ ingame的表格布局将是:gameactivity:activityid,userid,gameid,started,ended

DDL:

CREATE TABLE IF NOT EXISTS `steamonlineactivity` (
  `activityID` int(13) NOT NULL AUTO_INCREMENT,
  `userID` varchar(255) NOT NULL,
  `online` datetime DEFAULT NULL,
  `offline` datetime DEFAULT NULL,
  PRIMARY KEY (`activityID`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
Run Code Online (Sandbox Code Playgroud)

rsa*_*hez 4

如果我正确理解您的要求,如果该图代表用户活动:

       Day 
       12/1 12/2 12/3 12/4 ...
Hour 0  xx    x    x   xx
     1   x   xx        xx
     2 xxx    x    x   xx
     3   x              x
     4        x         x
     5   x              x
     6                  x
   ...
Run Code Online (Sandbox Code Playgroud)

您想知道 02:00 是一天中平均活动最高的时间(一行为 7 x),而 12/4 是最活跃的一天(一列为 10 x)。请注意,这并不意味着 12/4 的 02:00 是有史以来最活跃的时间,正如您在示例中看到的那样。如果这不是您想要的,请用输入和期望结果的具体示例进行澄清。

我们做出几个假设:

  • 活动记录可以在一个日期开始并在下一个日期结束。例如:线上2013-12-02 23:35、线下2013-12-03 00:13
  • 没有活动记录的持续时间超过 23 小时,或者此类记录的数量可以忽略不计。

我们需要定义“活动”的含义。我选择了在每种情况下更容易计算的标准。如果需要,两者都可以变得更准确,但代价是查询更复杂。

  • 一天中最活跃的时间将是有更多活动记录重叠的时间。请注意,如果用户在一小时内启动和停止多次,则会被多次计数。
  • 最活跃的一天将是一天中任何时间都有更多活跃的唯一用户的一天。

对于一天中最活跃的时间,我们将使用一个小型辅助表来保存 24 小时的数据。它还可以使用其他答案中描述的技术动态生成和连接。

CREATE TABLE hour ( hour tinyint not null, primary key(hour) );
INSERT hour (hour)
VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)
     , (11), (12), (13), (14), (15), (16), (17), (18), (19), (20)
     , (21), (22), (23);
Run Code Online (Sandbox Code Playgroud)

然后以下查询给出所需的结果:

SELECT hour, count(*) AS activity
  FROM steamonlineactivity, hour
 WHERE ( hour BETWEEN hour(online) AND hour(offline)
      OR hour(online) BETWEEN hour(offline) AND hour
      OR hour(offline) BETWEEN hour AND hour(online) )
 GROUP BY hour
 ORDER BY activity DESC;

SELECT date, count(DISTINCT userID) AS activity
  FROM ( 
       SELECT userID, date(online) AS date
         FROM steamonlineactivity
        UNION
       SELECT userID, date(offline) AS date
         FROM steamonlineactivity
   ) AS x
 GROUP BY date
 ORDER BY activity DESC;
Run Code Online (Sandbox Code Playgroud)