开发者

Counting records with start and end fields that envelop a given value

开发者 https://www.devze.com 2023-02-14 07:07 出处:网络
Suppose I have a table (MySQL) like this: CREATE TABLE sessions ( session_id INT NOT NULL AUTO_INCREMENT,

Suppose I have a table (MySQL) like this:

CREATE TABLE sessions (
    session_id INT NOT NULL AUTO_INCREMENT,
    name CHAR(12),
    start INT,
    end INT,
    PRIMARY KEY (session_id)
)

to track the users who are logged into an application. Each user login creates an entry in this table setting the start time (as an integer counting seconds from the Unix epoch), and logout updates this table setting the end time similarly. My problem is to find the number of logged in users at five-minute intervals, for a time range (typically a day).

What I have done so far is to write a procedure that loops over the data.

SET t = begin_time;
WHILE t <= end_time DO
    SELECT t, COUNT(1) FROM TABLE WHERE start <= t AND end >= t;
    SET t = t + 300;
END WHILE;

This is quite time consuming; I am looking for alternative solutions for this problem. Web references, pointers - any he开发者_运维百科lp will do.

Thanks in advance.


I think, you'll need the help of a number table to do a proper profiling for every point of time according to the given time range and interval between time points.

Here's a possible solution:

SET begin_time = ...
SET end_time = ...
SET interval_sec = 300;

CREATE TEMPORARY TABLE timestamps (unixtime int);
SET t = (begin_time + interval_sec - 1) div interval_sec;
WHILE t <= end_time DO
  INSERT INTO timestamps (unixtime) VALUES (t);
  SET t = t + interval_sec;
END WHILE;

SELECT
  t.unixtime,
  COUNT(s.session_id)
FROM timestamps t
  LEFT JOIN sessions s ON t.unixtime >= s.start AND t.unixtime < s.end;
GROUP BY t.unixtime

The 3rd line makes sure all the timestamps being profiled are the beginnings of 5-minute intervals according to the clock scale. If you would rather like them to base off the beginning of the time range specified, change it to simply SET t = begin_time;.

This solution counts active sessions at the specified moments. If it is possible for a user to have several concurrent sessions and you would like to know how many distinct users were online, you should replace COUNT(s.session_id) with COUNT(DISTINCT s.name).


SELECT (end-start)-(end-start)%300, COUNT(1) FROM session GROUP BY 1 ORDER BY 1;
0

精彩评论

暂无评论...
验证码 换一张
取 消