MySql查询时间间隔数据的直方图

mos*_*eri 6 mysql sql time-series

我有这种类型的事件输入

event user
event start
event end
event type
Run Code Online (Sandbox Code Playgroud)

插入到MySql表中,每个表都在自己的行中,用户+ start作为主键.

我需要按时间间隔(比如分钟)查询每个时间间隔发生的事件的直方图.就像是:

SELECT count(*) as hits FROM events 
WHERE type="browsing" 
GROUP BY time_diff("2015-1-1" AND "2015-1-2") / 60 * second
Run Code Online (Sandbox Code Playgroud)

但除了编写代码之外,我在SQL中找不到任何方法可以做到这一点,任何想法?

样本数据

user, start, end, type
1, 2015-1-1 12:00:00, 2015-1-1 12:03:59, browsing
2, 2015-1-1 12:03:00, 2015-1-1 12:06:00, browsing
2, 2015-1-1 12:03:00, 2015-1-1 12:06:00, eating
3, 2015-1-1 12:03:00, 2015-1-1 12:08:00, browsing
Run Code Online (Sandbox Code Playgroud)

结果应如下所示:

         ^
count    |
browsing |
users    |       *
         |       *  *  *  *
         | *  *  *  *  *  *  *  *
         --|--|--|--|--|--|--|--|--|--> minute
         0  1  2  3  4  5  6  7  8  9 
Run Code Online (Sandbox Code Playgroud)

tec*_*ude 7

您可以使用group by以您想要的级别执行此操作.以下是使用您提供的数据的示例:

首先是SQL来创建表并填充它.此处的ID列不是"需要",但如果表格很大或者有索引,则建议使用此列.

CREATE TABLE `test`.`events` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `user` INT NULL,
  `start` DATETIME NULL,
  `end` DATETIME NULL,
  `type` VARCHAR(45) NULL,
  PRIMARY KEY (`id`));

INSERT INTO events (user, start, end, type) VALUES 
(1, '2015-1-1 12:00:00', '2015-1-1 12:03:59', 'browsing'),
(2, '2015-1-1 12:03:00', '2015-1-1 12:06:00', 'browsing'),
(2, '2015-1-1 12:03:00', '2015-1-1 12:06:00', 'eating'),
(3, '2015-1-1 12:03:00', '2015-1-1 12:08:00', 'browsing');
Run Code Online (Sandbox Code Playgroud)

要获取有关事件数量的有序对数列表的持续时间列表:

然后可以使用timestampdiff函数轻松编写查询,如下所示:

SELECT 
    TIMESTAMPDIFF(MINUTE, start, end) as minutes,
    COUNT(*) AS numEvents
FROM
    test.events
GROUP BY TIMESTAMPDIFF(MINUTE, start, end)
Run Code Online (Sandbox Code Playgroud)

输出:

minutes      numEvents
3            3
5            1
Run Code Online (Sandbox Code Playgroud)

select中的第一个参数可以是FRAC_SECOND,SECOND,MINUTE,HOUR,DAY,WEEK,MONTH,QUARTER或YEAR中的一个.

以下是您可以执行的更多查询示例:

按小时划分的事件(应用楼层功能)

SELECT 
    TIMESTAMPDIFF(HOUR, start, end) as hours,
    COUNT(*) AS numEvents
FROM
    test.events
GROUP BY TIMESTAMPDIFF(HOUR, start, end)
Run Code Online (Sandbox Code Playgroud)

**按小时划分的事件,格式更好**

SELECT 
    CONCAT("<", TIMESTAMPDIFF(HOUR, start, end) + 1) as hours,
    COUNT(*) AS numEvents
FROM
    test.events
GROUP BY TIMESTAMPDIFF(HOUR, start, end)
Run Code Online (Sandbox Code Playgroud)

您可以通过各种选项进行分组,但这绝对可以帮助您入门.大多数绘图包都允许您指定任意xy坐标,因此您无需担心x轴上的缺失值.

获取特定时间的有序事件数量列表(用于记录): 请注意,这仅供参考.

现在进行查询.首先,您必须选择要用于分组的项目.例如,任务可能需要一分多钟,因此开始和结束将在不同的分钟内完成.对于所有这些示例,我将它们从开始时间开始,因为那是事件实际发生的时间.

要按分钟对事件计数进行分组,您可以使用如下查询:

SELECT 
     DATE_FORMAT(start, '%M %e, %Y %h:%i %p') as minute, 
     count(*) AS numEvents 
FROM test.events 
GROUP BY YEAR(start), MONTH(start), DAYOFMONTH(start), HOUR(start), MINUTE(start);
Run Code Online (Sandbox Code Playgroud)

请注意这些按所有项目分组的方式,从年份开始,分钟开始.我也将分钟显示为标签.结果输出如下所示:

minute                      numEvents
January 1, 2015 12:00 PM    1
January 1, 2015 12:03 PM    3
Run Code Online (Sandbox Code Playgroud)

这是您可以使用php获取的数据,并准备由其中一个图形库中的一个显示,在x轴上绘制分钟列,并在y轴上绘制numEvents.

以下是您可以执行的更多查询示例:

按小时划分的活动

SELECT 
     DATE_FORMAT(start, '%M %e, %Y %h %p') as hour, 
     count(*) AS numEvents 
FROM test.events 
GROUP BY YEAR(start), MONTH(start), DAYOFMONTH(start), HOUR(start);
Run Code Online (Sandbox Code Playgroud)

按日期划分的活动

SELECT 
    DATE_FORMAT(start, '%M %e, %Y') as date, 
    count(*) AS numEvents 
FROM test.events 
GROUP BY YEAR(start), MONTH(start), DAYOFMONTH(start);
Run Code Online (Sandbox Code Playgroud)

每个月的活动

SELECT 
    DATE_FORMAT(start, '%M %Y') as date, 
    count(*) AS numEvents 
FROM test.events 
GROUP BY YEAR(start), MONTH(start);
Run Code Online (Sandbox Code Playgroud)

每年的活动

SELECT 
    DATE_FORMAT(start, '%Y') as date, 
    count(*) AS numEvents 
FROM test.events 
GROUP BY YEAR(start);
Run Code Online (Sandbox Code Playgroud)

我还应该指出,如果此表的起始列上有索引,这些查询将快速完成,即使有数亿行也是如此.

希望这可以帮助!如果您对此有任何其他疑问,请与我们联系.