ここにいくつかの解決策があります。1 つを説明したいと思います。特定のニーズに合わせて使用/適応/拡張できることを願っています (注: 私は mysql 方言を使用しています。ms sql の場合、構文が少し異なる場合がありますが、アプローチが機能します):
1次のような構造の新しいテーブルを作成します。
create table changelog (
changetime datetime,
changevalue int,
totalsum int,
primary key (changetime)
);
2基本データの挿入:
insert into changelog
select changet, sum(cnts), 0
from
(
select start_time as changet, 1 as cnts from testlog
union all
select end_time as changet, -1 from testlog
) as q
group by changet;
3合計列を更新します。
update changelog as a set totalsum = ifnull((select sum(changevalue) from (select changet, sum(cnts) as changevalue, 0
from
(
select start_time as changet, 1 as cnts from testlog
union all
select end_time as changet, -1 from testlog
) as q
group by changet) as b where b.changet<=a.changetime),0);
注:ms sqlの場合with
、構文を試すことができます。これらの挿入/更新を1つのクエリとして実行できます
4この後、(質問のデータに基づいて)次のようになります。
2013-10-30 07:01:23 1 1
2013-10-30 08:01:23 1 2
2013-10-30 09:01:23 1 3
2013-10-30 09:01:24 1 4
2013-10-30 16:12:03 -1 3
2013-10-30 17:02:03 -1 2
2013-10-30 17:12:03 -1 1
2013-10-30 18:12:03 -1 0
ご覧のとおり、max はすでにここにログインしていますが、ここに 1 つの問題があります。範囲のデータを選択する必要があると想像してください: 08:00-08:01、テーブルにデータがないため、次のようなクエリは機能しません:
SELECT max(totalsum)
FROM changelog
where changetime between cast(@startrange as datetime) and cast(@endrange as datetime)
ただし、次のように変更できます。
SELECT max(totalsum)
from
(
select max(totalsum) as totalsum FROM changelog
where changetime between cast(@startrange as datetime) and cast(@endrange as datetime)
union all
select totalsum from changelog where changetime=(select max(changetime) from changelog where changetime<cast(@startrange as datetime))
) as q;
つまり、基本的には、範囲に加えて、期間が始まる前に最後の行をフェッチして、範囲の開始時に何人のユーザーがいたかを調べる必要があります
5次に、平均を計算します。平均は、理解している内容に応じて、ちょっとトリッキーな関数です。異なる結果、1 秒あたりの平均ユーザー数、または平均ワークロードが存在する可能性があります。
違いは次のとおりです。
100 users logged in at 09:00
98 users logged out at 09:01
1 user logged out at 09:02
Selection range: 09:00 - 09:59 (inclusive)
1 分あたりの平均は、1 分間にログインしたすべてのユーザーの合計を 60 で割った値になります。
(100 + 2 + 1 + 57*1)/60 = 2.6(6) user per minute
ただし、平均ワークロードは (max(logged_users)+min(logged_users)) / 2 として計算できます。
(100 + 1)/2 = 50.5 users, this is average simultaneous users logged in system
別の平均は、SQL avg (sum(values)/count(values)) を使用して計算できます。
(100+98+1)/3 = 66.3(3) - another average workload in persons
最初の式は、同時に 2.65 ユーザーしかいないことを示していますが、2 番目の式は「神聖な #*&#@#@、同時に 50.5 ユーザーです」と示しています。
もう一つの例:
100 users logged in at 09:00
99 users logged out at 09:58
1 user logged out at 09:59
Selection range: 09:00 - 09:59 (inclusive)
最初の式は(100*58 + 2 + 1)/60 = 96.71(6)
ユーザーを提供し、2 番目の式はユーザーを引き続き提供し50.5
、3番目の式は引き続きユーザーを提供します66.3(3)
どの平均があなたに最も適していますか?
最初の平均を計算するstored procedure
には、期間の分/秒ごとにデータを取得し、除算後に集計する必要があります。
2 番目のバリアントを計算するには: 選択min/max
して 2 で割るだけです
3 番目のバリアント: avg
max の代わりに使用
注 #1: もちろん、このすべてのアプローチは膨大なトラフィックで非常に遅いため、高速に取得できるデータを含む「事前計算済み」のテーブルをいくつか用意することをお勧めします (たとえば、次のように 1 時間ごとにデータを取得できますYYYY-MM-DD HH loggedInatStart, min, avg, median, max, loggedInatEnd
) 。
注 #2:統計目的で中央平均の方が興味深い場合があります。それを取得するには、1 分ごとにログインしたユーザー数を計算し、個別の値を選択し、このリストから中央を選択します (私の例では、2 と 2 が得られます)。 2)、またはすべての値を選択し、中央の値を選択します(私の例では、1と99が得られます)