I have the following table in PostgreSQL 9.4, which persists users log on/off events (log on is event_type
1, log off is event_type
0).
CREATE TABLE user_online_offline_events (
id serial,
user_id int4,
event_type int4,
created_at timestamp
);
Sample data:
INSERT INTO user_online_offline_events
(id, user_id, event_type, created_at)
VALUES (1, 123, 1, '2015-10-07 12:15:00'),
(2, 123, 0, '2015-10-07 12:25:00'),
(3, 123, 1, '2015-10-07 12:45:00'),
(4, 123, 0, '2015-10-07 13:10:00');
I'd like to calculate the number of minutes each user was logged-on per hour:
| id | user_id | time | minutes logged on |
+----+---------+----------+-------------------+
| 1 | 123 | 12:00:00 | 30 |
| 2 | 123 | 13:00:00 | 10 |
This is my WIP version. It's not really elegant, it still has the hour hard coded in, ignores user_ids and assumes online-offline events are consecutive:
select time, sum(minutes) / 60 as minutes from (
SELECT
date_trunc('hour', time) as time,
CASE
WHEN event_type = 0 AND lag(event_type, 1) OVER w = 1
THEN
extract(EPOCH FROM time - lag(time, 1) OVER w)
WHEN event_type = 0 AND lag(event_type, 1) OVER w ISNULL
THEN
extract(EPOCH FROM time - date_trunc('hour', created_at))
WHEN event_type = 1 AND lead(event_type, 1) OVER w ISNULL
THEN
extract(EPOCH FROM date_trunc('hour', time) + INTERVAL '1 hour' - time)
ELSE 0
END AS minutes
FROM user_online_offline_events
WHERE date_trunc('hour', time) = '2015-10-07 12:00:00'
WINDOW w AS ( ORDER BY time )
ORDER BY time
) m group by time;
How to do this properly?
CREATE TABLE
script or what you get with\d user_online_offline_events
in psql. And always your version of Postgres, please. Plus: define how to handle unmatched logging events: log-on without log-off and vice versa. And times never wrap around?user_id
distinctly?