Question

I have an application writing to MySQL with the below audit table format. I need to determine the current number of users logged in to the system at any given time during the day.

I have tried this with various self joins, sub queries, timediff, and even converting to unixtime plus some simple math, however I am unable to come up with a solution that is acceptable.
Any pointers or assistance is appreciated greatly.


audit_table

user | action | time
-----|--------|------
  1  | login  | 2013-07-02 00:37:00
  2  | login  | 2013-07-02 00:38:00
  1  | logout | 2013-07-02 00:39:30
  3  | login  | 2013-07-02 00:40:00
  2  | logout | 2013-07-02 02:30:00


Needed format: hour of 24 hour day | number of users logged in during that hour
Example (Note that user 3 has not logged out yet, thus still showing active in the count in hour 3)

hour | usersloggedin
-----|---------------
  0  |  3
  1  |  2
  2  |  2
  3  |  1
Was it helpful?

Solution

Before all you need to create a table for example called hours_table with number from 00 to 23:

CREATE TABLE `hours_table` (`hour` char(2) DEFAULT NULL); 

hour
----
00
01
02
03
04
..

After you execute this query:

SELECT  hour, (count(DISTINCT(li.user)) - count(DISTINCT(lo.user))) AS usersloggedin  FROM hours_table    
LEFT JOIN audit_table AS li ON  DATE_FORMAT(li.time, '%Y%m%d%H')<=CONCAT('20130702',hour)  AND DATE_FORMAT(li.time, '%Y%m%d')='20130702' AND li.action='login'
LEFT JOIN audit_table AS lo ON  DATE_FORMAT(lo.time, '%Y%m%d%H')<CONCAT('20130702',hour)  AND DATE_FORMAT(lo.time, '%Y%m%d')='20130702' AND lo.action='logout' 
GROUP BY hour

In place of 20130702 you put an other day in format yyyymmdd remove DATE_FORMAT(time, '%Y%m%d')='20130702' if you consider user logged yesterday active today.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top