1

アプリケーションに同時にログオンできるユーザーの最大数を計算するコードがあります。ログインテーブルは次のように構成されています。

idLoginLog |  username  |        Time         |  Type  |
--------------------------------------------------------
     1     |  pauljones | 2013-01-01 01:00:00 |    1   |
     2     |  mattblack | 2013-01-01 01:00:32 |    1   |
     3     |  jackblack | 2013-01-01 01:01:07 |    1   |
     4     |  mattblack | 2013-01-01 01:02:03 |    0   |
     5     |  pauljones | 2013-01-01 01:04:27 |    0   |
     6     |  sallycarr | 2013-01-01 01:06:49 |    1   |

同時にログオンしたユーザーの最大数を確認するコードは次のとおりです (アプリケーションが適切に終了せずに強制終了された場合など、明示的にログアウトしないユーザーを処理するセクションがあります)。

SET @logged := 0;
SET @max := 0;

SELECT 
  idLoginLog, type, time,
  (@logged := @logged + IF(type, 1, -1)) AS logged_users,
  (@max := GREATEST(@max, @logged)) AS max_users
FROM ( -- Select from union of logs and records added for users not explicitely logged-out
  SELECT * from logs
  UNION
  SELECT 0 AS idLoginnLog, l1.username, ADDTIME(l1.time, '0:30:0') AS time, 0 AS type
  FROM -- Join condition matches log-out records in l2 matching a log-in record in l1
    logs AS l1
    LEFT JOIN logs AS l2
    ON (l1.username=l2.username AND l2.type=0 AND l2.time BETWEEN l1.time AND ADDTIME(l1.time, '0:30:0'))
  WHERE
    l1.type=1
    AND l2.idLoginLog IS NULL -- This leaves only records which do not have a matching log-out record
) AS extended_logs 
ORDER BY time;

SELECT @max AS max_users_ever;

http://sqlfiddle.com/#!2/9a114/34

上記のコードは、次のスタック オーバーフローの質問 で達成されました。MySQL を使用してこれまでにオンラインになったほとんどのユーザーを計算する

ユーザーがログオンしたときにログイン エントリがテーブルに書き込まれず、ログアウト エントリしかないことがあるという問題が発生しました。これは計算を完全に台無しにします。以前の「ログイン」エントリがないエントリを無視するようにクエリを更新するにはどうすればよいですか? または、上記のコードがより合理的な結果を達成できるように、たとえば、単一の「ログアウト」エントリの2分前に「ログイン」エントリを追加するにはどうすればよいですか?

4

1 に答える 1