在MySQL中按时间间隔聚合数据

时间:2009-12-10 02:57:49

标签: mysql group-by aggregate

基本上我想要的是根据时间跨度在表格中聚合一些值。

我所做的是,每15分钟拍摄一次系统快照,我希望能够在很长一段时间内绘制一些图表。如果显示太多的点(除了渲染速度非常慢)之外,图形会变得非常混乱,我想通过对多个点进行平均来将多个点聚合到一个点来减少点数。

为此,我必须能够通过我可以定义的桶(每日,每周,每月,每年......)进行分组,但到目前为止,我的所有实验都没有运气。

我可以申请一些技巧吗?

3 个答案:

答案 0 :(得分:10)

我有一个类似的问题:collating-stats-into-time-chunks并且答案非常好。从本质上讲,答案是:

也许你可以使用DATE_FORMAT()函数和分组。这是一个例子,希望你能适应你的确切需求。

SELECT
    DATE_FORMAT( time, "%H:%i" ),
    SUM( bytesIn ),
    SUM( bytesOut )
FROM
    stats
WHERE
    time BETWEEN <start> AND <end>
GROUP BY
    DATE_FORMAT( time, "%H:%i" )

如果您的时间窗口超过一天并且您使用示例格式,则不同日期的数据将汇总到“每小时”桶中。如果原始数据不是完全按小时计算,则可以使用“%H:00”将其平滑。

感谢马丁克莱顿为他提供的答案。

答案 1 :(得分:2)

通过执行以下操作,很容易将时间截断到最后15分钟(例如):

SELECT dateadd(minute, datediff(minute, '20000101', yourDateTimeField) / 15 * 15, '20000101') AS the15minuteBlock, COUNT(*) as Cnt
FROM yourTable
GROUP BY dateadd(minute, datediff(minute, '20000101', yourDateTimeField) / 15 * 15, '20000101');

使用类似的截断方法按小时,星期,等等分组。

您可以使用以下命令将其包装在CASE语句中以处理多种方法:

GROUP BY CASE @option WHEN 'week' THEN dateadd(week, .....

答案 2 :(得分:0)

作为@cmroanirgo的补充,我不需要数据的“总和”,而是平均数(以查看游戏服务器的平均FPS /玩家数)。而且,我需要每5分钟详细查看一次-或查看整周的数据(每分钟存储一次数据)。

作为示例,您可以使用SQL命令AVG代替SUM来获取平均值。另外,您还必须将选定的值命名为某种名称,并且该名称不应是实际的字段名(以后在查询中会发生冲突)。这是我用来按小时汇总1周平均值的查询:

SELECT
    DATE_FORMAT( moment, "%Y-%m-%d %H:00" ) as _moment,
    AVG( maxplayers ) as _maxplayers,
    AVG( players ) as _players,
    AVG( servers ) as _servers,
    AVG( avarage_fps ) as _avarage_fps,
    AVG( avarage_realfps ) as _avarage_realfps,
    AVG( avarage_maxfps ) as _avarage_maxfps
FROM
    playercount
WHERE
    moment BETWEEN "<date minus 1 week>" AND "<now>"
GROUP BY
    _moment
ORDER BY moment ASC

然后将其(与PHP一起)用于Bootstrap图;

<?php
//Do the query here

foreach ($result->fetch_all(MYSQLI_ASSOC) as $item) {
    $labels[] = $item['_moment'];
    $maxplayers[] = $item['_maxplayers'];
    $players[] = $item['_players'];
    $servers[] = $item['_servers'];
    $fps[] = $item['_avarage_fps'];
    $fpsreal[] = $item['_avarage_realfps']/10;
    $fpsmax[] = $item['_avarage_maxfps'];
}
?>

var playerChartId = document.getElementById("playerChartId");
var playerChart = new Chart(playerChartId, {
    type: 'line',
    data: {
        labels: ["<?= implode('","', $labels); ?>"],
        datasets: [
            {
                data: [<?= implode(',', $servers); ?>],
                borderColor: '#007bff',
                pointRadius: 0
            },
            //etc...