SQL: get current online player count using login/logout timestamp - mysql

I have a MySQL table that comprises uid, login/logout status flat, timestamp, for example:
uid flag time
123 login 10:00:00
123 logout 10:10:00
321 login 10:08:00
321 logout 10:18:00
Now I want to display online player count for every minute between 10:08 to 10:09. What is expected:
Minute current_player_cnt
10:07 1
10:08 2
10:09 2
I can export data as csv file and do this using python, but I want directly do this using sql and cannot find a function that could help.
You do not need to give the entire sql sentence, just give a function name will be fine. Any suggestion is appreciated.

One option is to join using a calendar table, e.g.
SELECT
t1.Minute,
COUNT(t2.uid) AS current_player_cnt
FROM
(
SELECT '10:07:00' AS Minute UNION ALL
SELECT '10:08:00' UNION ALL
SELECT '10:09:00'
) t1
LEFT JOIN
(
SELECT uid, MIN(time) AS login_time, MAX(time) AS logout_time
FROM yourTable
GROUP BY uid
) t2
ON t1.Minute BETWEEN t2.login_time AND t2.logout_time OR
(t1.Minute >= t2.login_time AND t2.login_time = t2.logout_time)
GROUP BY
t1.Minute;
Demo

Related

calculate the maximum and minimum number of days between each person's travels

People travel in pairs. How to find the maximum and minimum number of days between trips every user?
People:
id
user
1
Harry
2
George
3
Thomas
4
Jacob
5
Jack
6
Oliver
Travels:
id
date
user1
user2
1
2005-10-03
2
3
2
2005-10-04
1
4
3
2005-10-05
5
6
4
2005-10-06
1
3
5
2005-10-07
2
4
6
2005-10-08
3
5
7
2005-10-10
1
4
8
2005-10-11
5
2
9
2005-10-15
6
4
I tried to solve this problem in the following way, but I still do not understand how to solve this problem:
select People.id,People.user, count(*)
from People
INNER join
(SELECT MIN(TIMESTAMPDIFF(day, t1.date, t2.date)) as mintime,max(TIMESTAMPDIFF(day, t1.date, t2.date))
from Travels as t1
join Travels as t2 on t1.PERSON_1 = t2.PERSON_1
WHERE t1.date< t2.date
GROUP BY t1.PERSON_1) as t3
group by People.id
There is an idea to use the position function to iterate over each user, and then, as a result, look at the dates and find the minimum and maximum, but I still don't understand how to do this
Best is to do it in steps with subqueries, as below (comments are in the query):
select user, max(dateDiff)
from (
select
user,
-- get the diff between previous and current row date to get diff between trips
datediff(date, lag(date) over (partition by user order by date)) dateDiff
from (
-- full flat list of all users and trip dates
select date, user1 `user`
from testtbl
union all
select date, user2
from testtbl
) a
) a group by user
SQL fiddle
Note that I used windowed function which are not avaiable in MySql 5 and below.

Find MySql concurrent user per hour in a week

This is my table, i want to find concurrent user per hour for a given week
I am trying to calculate number of concurrent users in a time range. The input looks something like the below
Table
id user_id login_time
1 23 2016-06-08 09:10:00
2 24 2016-06-08 08:55:00
3 25 2016-06-08 09:29:00
4 26 2016-06-08 09:40:00
5 27 2016-06-08 09:08:00
6 28 2016-06-09 13:40:00
7 31 2016-06-09 14:04:00
How to get the concurrent users in time range ?
Expected Output Table
Date
Hour
User
2014-08-04
0
3
2014-08-04
1
2
2014-08-04
2
0
2014-08-05
0
1
Similar question
concurrent users sql
I created a DBFIDDLE
first I entered the data from your question
half-way I changed data to what was given here: http://sqlfiddle.com/#!9/67356f/2
first the cte1 contains the first and last date from users.
cte2 contains all the dates between StartDate and EndDate
cte3 contains all (24) hours for the dates.
After this is is just counting to see if a user is logged in.
WITH RECURSIVE cte1 AS (
SELECT
DATE(MIN(login_time)) StartDate,
DATE(MAX(login_time)) EndDate
FROm users),
cte2 AS (
SELECT cte1.StartDate
from cte1
union all
select DATE_ADD(cte2.StartDate, INTERVAL 1 DAY)
from cte2
cross join cte1 where cte2.StartDate < cte1.EndDate
),
cte3 AS (
SELECT StartDate, 0 as H
FROM cte2
UNION ALL
SELECT StartDate, H+1 FROM cte3 WHERE H<24
)
select * from (
select
StartDate as `Date`,
H as `hour`,
(SELECT count(*) from users
WHERE login_time BETWEEN DATE_ADD(StartDate, interval H HOUR) AND DATE_ADD(StartDate, interval (H+1) HOUR)
) as `Count`
from cte3) x
where x.`Count` <>0
order by 1,2;
You can begin with this, but (from my opinion) it has no sense the result you are trying to get because you need to calculate the time:
If a user enters 9:30 and left 9:35 and re-enter 9:45 is not a concurrent user but you get this in the SQL.
If a user enters 9:59 and enter 10:01 you have a concurrent user but you won't see this with this logic of "hour"
Concurrent user with different day (23:59 and 00:01 logins)
In any case, the SQL you are asking for:
SQL Fiddle
SELECT
up.user_id,
up.diff as TimeDiff,
FROM
(
SELECT TIMESTAMPDIFF(HOUR,u1.login,u2.login) as diff, u1.user_id FROM users u1
JOIN users u2
ON u1.user_id = u2.user_id
AND u1.login < u2.login ) up
WHERE up.diff < 1
And without DIFF time (as you requested):
SELECT
g.id,
g.hour,
g.datelogin,
COUNT(*) as times
FROM
(SELECT HOUR(login) as hour, DATE(login) as datelogin, id FROM users) g
GROUP BY datelogin, hour, id
HAVING COUNT(*) > 1 -- This will show only counts is bigger than 1

SQL query to get multiple rows with different timestamps

I am attempting get some data with their latest timestamps. sets of data have different timestamps which i need to get using their timestamps. for example:
id
testcase_id
user
timestamp
1
2
abbc
2013-01-13 15:00:00
2
2
pbbb
2013-01-13 15:05:00
3
4
dddd
2013-01-13 15:05:00
4
4
abbc
2010-01-10 16:04:00
For abbc need to get row 1 which have latest timestamp(2013-01-13 15:00:00) and i need row 2 with pbbb (2013-01-13 15:05:00) and row 3 dddd (2013-01-13 15:05:00). I have this timestamp data for each user in backend just need a proper query to fetch all those rows using timestamps.
Note: There could be multiple users with same timestamps, ex - if 10 users have same timestamp as abbc i will require all those users.
JPQL is picky about the syntax it allows. You may try using correlated subqueries here:
select e
from your_entity e
where e.timestamp = (select max(f.timestamp)
from your_entity f where f.user = e.user)
Try CTE + analytical function row_number()
with t1 as (
select id, testcase_id, user, timestamp,
row_number() over (partition by user order by timestamp desc) rno
from your_table)
select select id, testcase_id, user, timestamp
from t1
where rno = 1

Prior row depends on value of current row

The following query shows login information based on the userId. If a user closes their browser without logging off or the session expires, the logoff_date will remain null as in the example below.
userId logon_date logoff_date
1 2012-01-01 10:00:00 2012-01-01 12:00:00
1 2012-01-01 09:00:00 NULL
Because there is a newer logon_date of 2012-01-01 10:00:00, I know that the user must have killed the session for the login_date of 2012-01-01 09:00:00.
Here is my query:
SELECT userId, logon_date, logoff_date
FROM user_logon
WHERE user_id = 2
What I would like is to count only active sessions. In order to do this, I need to skip the rows where the logoff_date is missing if there is a newer row with the same userId.
How about this:
SELECT l.*
FROM user_logon l
INNER JOIN (SELECT MAX(logon_date) mdate,
user_id
FROM user_logon
GROUP BY user_id) x ON x.user_id = l.user_id
AND l.logon_date = x.mdate
WHERE l.logoff_date IS NULL
?
PS: This query implies that for each date there is only one record for particular user

MySQL get set of data with distinct values

I have a simple problem; one which I thought would have a simple solution. Imagine a Table like this:
Name Timestamp Data
Bob 2011-01-01 01:00:00 Hi
Alice 2011-02-02 02:00:00 Hello
Alice 2011-03-03 03:00:00 Hello
Bob 2011-04-04 04:00:00 Bye
Charlie 2011-05-05 05:00:00 Cheese
Charlie 2011-06-06 06:00:00 Toast
All I want is to be able to run a query that shows the most recent entry for each Name. So with the above table, I would like an output like this:
Name Timestamp Data
Bob 2011-04-04 04:00:00 Bye
Alice 2011-03-03 03:00:00 Hello
Charlie 2011-06-06 06:00:00 Toast
Ordered by Data. I can't figure out how to do this. I though I could just do:
SELECT DISTINCT(Name), timestamp, Data FROM Table ORDER BY Data
But this doesn't work. Any help would be most appreciated,
Cheers.
Use this query to get last unique values,
SELECT * FROM (select * from `table` order by date DESC) t group by name
SELECT DISTINCT Name, Timestamp, Data
FROM Table
WHERE Timestamp =
(
SELECT MAX(Timestamp)
FROM Table AS tempTable
WHERE Table.Name = tempTable.Name
)
select t1.* from table as t1
inner join (
select name,max(`timestamp`) as `timestamp`
from table
group by name) as t2
on t1.name = t2.name and t1.`timestamp` = t2.`timestamp`