MySQL获取组中每x分钟的列的平均值和总和

Posted

技术标签:

【中文标题】MySQL获取组中每x分钟的列的平均值和总和【英文标题】:MySQL get the average and sum of a columns for each x minutes of a group 【发布时间】:2014-07-07 18:12:26 【问题描述】:

我尝试了几个小时来找出一个查询,但我没有运气。我什至不知道是否可以仅使用一个查询。

我有一张这样的桌子

id - server_id - players_online - performance - timestamp

此表每 5-10 分钟包含每台服务器的大约一条记录。 问题是,我想获得平均性能和每 20 分钟间隔的 player_online 总和,但由于同一服务器可能在这 20 分钟内多次出现,它可能会破坏我想要的最终结果:

    按 20 分钟间隔分组 每个 server_id 每 20 分钟只保留一个结果 获取所有服务器每 20 分钟的平均性能和 player_online 总和

使用 ROUND(timestamp/(20*60)) 我可以轻松地按 20 分钟间隔分组,但我该如何继续。你会怎么写查询?

到目前为止我尝试过的查询:

SELECT avg(performance) as performance, sum(playersOnline) as playersOnline, timestamp
    FROM stats_server
    GROUP BY ROUND(timestamp/(1200))

示例数据: http://www.mediafire.com/download/z629q3g38qhr46h/stats_server.sql.gz

结果(本次来自服务器的平均值/总和):

timestamp     | performance | online players
1404757200000 | 93          | 125
1404758400000 | 92          | 120
1404759600000 | 96          | 133
1404759800000 | 93          | 168
1404751000000 | 88          | 122
1404751200000 | 94          | 134

解决方案:

SELECT min20 * 1200 AS timestamp, AVG( performance ) AS performance, SUM( players ) AS playersOnline
        FROM (
            SELECT serverID, FLOOR( UNIX_TIMESTAMP( timestamp ) / 1200 ) AS min20, AVG( performance ) AS performance, AVG( playersOnline ) AS players
            FROM stats_server
            GROUP BY min20, serverID
        ) tmp
        GROUP BY min20
        ORDER BY timestamp

【问题讨论】:

【参考方案1】:

您的问题在于您的信息设计。如果当时有 10 个人在线,稍后有 10 个人在线,你不能说是有 10 个人在线还是 20 个人在线。可能是之前的 10 个人,也可能是 10 个新人。

如果您想获得准确的在线人数,您必须保存有助于区分用户的信息,例如 IP 地址。

根据您的记录,唯一合乎逻辑的事情就是在网上获取最多的人,比如说

max(playersOnline)

这至少是在线玩家总数的下限。

【讨论】:

如果一个服务器在 20 分钟内有多条记录,获取哪条记录并不重要。我们可以使用玩家最多的那个,或者平均的或者随机的。 我要补充一点:最大的 playerOnline 是在多条记录之间共享的 -> 我们必须将所有服务器加在一起【参考方案2】:

SELECT min20 * 1200 AS timestamp, AVG( performance ) AS performance, SUM( players ) AS playersOnline FROM ( SELECT serverID, FLOOR( UNIX_TIMESTAMP( timestamp ) / 1200 ) AS min20, AVG( performance ) AS performance, AVG( playersOnline ) AS players FROM stats_server GROUP BY min20, serverID ) tmp GROUP BY min20 ORDER BY timestamp

【讨论】:

【参考方案3】:

如果您使用的是 mysql 或 SQL,并且时间戳是标准的 unix 时间戳,则最好将时间戳格式化为日期/时间格式,然后对结果进行分组。

看看http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-format

例如,您可以将时间戳更改为 DD MM YYYY HH:MM 并按此分组

GROUP BY server_id, DATE_FORMAT(timestamp, '%W %M %Y %H:%S')

编辑:认为您需要先按 server_id 分组

编辑 2:尝试以下操作 - 无法真正测试,因为使用 now() 时时间戳已用完

SELECT serverID, avg(performance), sum(playersOnline), DATE_FORMAT(timestamp, '%W %M %Y %H:%S') FROM `stats_server` where timestamp > now()-1200 group by ROUND(timestamp/(1200)), serverID order by serverID, ROUND(timestamp/(1200)) asc

【讨论】:

当我先按服务器ID分组时,我如何获得多个结果? 我以为您希望结果中每台服务器有一行,而表中的每台服务器会有多行? 啊,对不起,看一下结果示例,我想要每 20 分钟一行。所有服务器在线玩家的平均性能和总和。 您会为此查询查看一台服务器吗? 我有多个服务器,我想获取一个图表的数据,这个图表显示了所有服务器每 20 分钟的当前在线玩家和平均性能。

以上是关于MySQL获取组中每x分钟的列的平均值和总和的主要内容,如果未能解决你的问题,请参考以下文章

PHP / SQL - 获取另一列的总和

Datagrid:计算页脚中列的平均值或总和

计算 2 行 2 个不同表的平均值

计算表中每 x 行的平均值并创建新表

尝试使用 MySQL 创建具有同一表中另一列的季节至今平均值的列

如何获得 2 个不同 WHERE 子句的列的平均值?