Als ik uw vereisten goed heb begrepen, als deze grafiek gebruikersactiviteit weergeeft:
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
...
Je wilt weten dat 02:00 de tijd van de dag is met de hoogste gemiddelde activiteit (een rij met 7 x
), en 12/4 was de meest actieve dag (een kolom met 10 x
). Merk op dat dit niet betekent dat 02:00 van 12/4 het meest actieve uur ooit was, zoals je in het voorbeeld kunt zien. Als dit niet is wat je wilt, verduidelijk dan met concrete voorbeelden van input en gewenst resultaat.
We maken een paar aannames:
- Een activiteitenrecord kan op de ene datum beginnen en op de volgende eindigen. Bijvoorbeeld:online
2013-12-02 23:35
, offline2013-12-03 00:13
. - Geen enkele activiteitsrecord heeft een duur van meer dan 23 uur, of het aantal van dergelijke records is te verwaarlozen.
En we moeten definiëren wat 'activiteit' betekent. Ik koos de criteria die in elk geval gemakkelijker te berekenen waren. Beide kunnen indien nodig nauwkeuriger worden gemaakt, ten koste van complexere zoekopdrachten.
- De meest actieve tijd van de dag is het uur waarmee meer activiteitenrecords elkaar overlappen. Houd er rekening mee dat als een gebruiker meer dan één keer per uur start en stopt, deze meer dan één keer wordt geteld.
- De meest actieve dag is de dag waarop er meer unieke gebruikers waren die op elk moment van de dag actief waren.
Voor de meest actieve tijd van de dag gebruiken we een kleine hulptabel met de 24 mogelijke uren. Het kan ook on-the-fly worden gegenereerd en samengevoegd met de technieken die in andere antwoorden worden beschreven.
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);
Dan geven de volgende zoekopdrachten de vereiste resultaten:
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;