要件を正しく理解し、このグラフがユーザーアクティビティを表している場合:
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
...
02:00が、平均アクティビティが最も高い時刻(7 x
の行)であることを知りたいとします。 )、12/4が最もアクティブな日でした(10 x
の列 )。これは、例でわかるように、12/4の02:00がこれまでで最もアクティブな時間であったことを意味するものではないことに注意してください。これが希望どおりでない場合は、入力と望ましい結果の具体的な例を使用して明確にしてください。
いくつかの仮定をします:
- アクティビティレコードは、ある日付で開始し、次の日付で終了することができます。例:オンライン
2013-12-02 23:35
、オフライン2013-12-03 00:13
。 - 23時間を超える期間のアクティビティレコードがないか、そのようなレコードの数はごくわずかです。
そして、「アクティビティ」が何を意味するのかを定義する必要があります。いずれの場合も計算しやすい基準を選択しました。必要に応じて両方をより正確にすることができますが、クエリがより複雑になります。
- 最もアクティブな時刻は、より多くのアクティビティレコードが重複する時間になります。ユーザーが1時間に複数回開始および停止した場合、複数回カウントされることに注意してください。
- 最もアクティブな日は、その日のいつでもアクティブだったユニークなユーザーが多かった日です。
最もアクティブな時間帯には、24時間を保持する小さな補助テーブルを使用します。また、他の回答で説明されている手法を使用して、その場で生成および結合することもできます。
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);
次に、次のクエリで必要な結果が得られます。
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;