Reputation: 1860
I tried multiple hours to figure out a query for this but I had no luck. I don't even know if it is possible with just one query.
I have a table like this
id - server_id - players_online - performance - timestamp
This table includes about one record for each server every 5-10 minutes. The thing is, I wanna get the average performance and the sum of players_online per 20 minute interval but as the same server can occur multiple times within these 20 minutes it can corrupt the final result that I want:
With ROUND(timestamp/(20*60)) I can easily group by the 20 min interval, but how do I proceed. How would you write query?
The query I tried to so far:
SELECT avg(performance) as performance, sum(playersOnline) as playersOnline, timestamp
FROM stats_server
GROUP BY ROUND(timestamp/(1200))
Example Data: http://www.mediafire.com/download/z629q3g38qhr46h/stats_server.sql.gz
Result (average/sum from servers for this time) :
timestamp | performance | online players
1404757200000 | 93 | 125
1404758400000 | 92 | 120
1404759600000 | 96 | 133
1404759800000 | 93 | 168
1404751000000 | 88 | 122
1404751200000 | 94 | 134
SOLUTION:
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
Upvotes: 1
Views: 1437
Reputation: 1860
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
Upvotes: 1
Reputation:
If you are using MySql or SQL and the timestamp is a standard unix timestamp you are best formatting the timestamp to a date / time format to then group the results.
have a look at http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-format
so for example you could change the timestamp to be DD MM YYYY HH:MM and group by that
GROUP BY server_id, DATE_FORMAT(timestamp, '%W %M %Y %H:%S')
EDIT: Think you need to group by server_id first
EDIT 2: Try the following - can't really test as the timestamps are out when using 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
Upvotes: 0
Reputation: 272
Your problem lies with your information design. If there are 10 people online at a moment and 10 poeple online a moment later, you cannot say if there were 10 or 20 people online. It could have been the same 10 people like the moment before or 10 new people.
If you want to get the exact number of people online, you have to save information that help to distinguish your users, like IP-Adresses.
Based on your records, the only logical thing would be to fetch the maximum of people online, say
max(playersOnline)
which is at least a lower bound for the sum of players online.
Upvotes: 1