In Name Out
2017-01-01 10:00:00 Sam 2017-01-01 17:00:00
2017-01-18 10:00:00 James 2017-01-18 12:00:00
2017-01-18 10:00:00 John NULL -> means still in office
How do I find all people who is in office at 2017-01-18 11:00:00 only for example?
SELECT * FROM Table WHERE '2017-01-08 11:00:00' BETWEEN IN AND OUT
-> This only returns James. (should be James and John)
SELECT * FROM Table WHERE '2017-01-08 11:00:00' BETWEEN IN AND NOW()
-> This returns Sam, James, John (should be James and John only)
Anyone can help? Somehow a I need to replace NULL (Out) Column with current timestamp. But using NOW() causes a problem for the BETWEEN statement.
Try this:
SELECT *
FROM myTable
WHERE '2017-01-18 11:00:00' BETWEEN `IN` AND COALESCE(`OUT`, NOW())
The query uses COALESCE to replace a NULL value in column OUT with the current date/time value.
Demo here
Related
I have table in MySQL with times spent by customers and I need to find the most busy 30 mins.
CREATE TABLE Customer
(id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
customerId int NOT NULL,
arrival datetime,
leaving datetime);
INSERT INTO Customer
(customerId, arrival, leaving)
VALUES
(1, '2018-01-01 10:00:00', '2018-01-01 12:00:00'),
(2, '2018-01-01 11:00:00', '2018-01-01 12:00:00'),
(3, '2018-01-01 11:30:00', '2018-01-01 12:30:00'),
(4, '2018-01-01 13:30:00', '2018-01-01 14:30:00')
;
Expected result is something like multiplerows with time and number of customers:
10:00 10:30 1
10:30 11:00 1
11:00 11:30 2
11:30 12:00 3
12:00 12:30 1
I can easily make 5 sql queries and get the result (I made some view in similar problem https://stackoverflow.com/a/59478411/11078894 ), but I do not know how to get the result with 1 query.
Please how to make subintervals in MySQL? Thx
Here is a solution based on union all and window function (available in SQL 8.0) that gets you quite close:
select
dt start_dt,
lead(dt) over(order by dt) end_dt,
sum(sum(cnt)) over(order by dt) cnt
from (
select arrival dt, 1 cnt from Customer
union all
select leaving, -1 from Customer
) t
group by dt
order by dt
The logic is to increment a global counter on each arrival and decrement it on each leave. You can then aggregate and do a window sum.
The only difference with your expected results is that this query does not generate a fixed list of intervals, but instead a list of intervals for which the number of customer is constant, as you can see in this demo:
start_dt | end_dt | cnt
:------------------ | :------------------ | --:
2018-01-01 10:00:00 | 2018-01-01 11:00:00 | 1
2018-01-01 11:00:00 | 2018-01-01 11:30:00 | 2
2018-01-01 11:30:00 | 2018-01-01 12:00:00 | 3
2018-01-01 12:00:00 | 2018-01-02 12:30:00 | 1
2018-01-02 12:30:00 | | 0
Thanks to the post from GMB I found the solution also for the SQL 5
Some view:
CREATE OR REPLACE VIEW changeTimeView AS
select arrival AS changeTime, 1 cnt from Customer
union all
select leaving, -1 from Customer
ORDER BY changeTime
After the view is created:
SELECT DISTINCT chT2.changeTime, (SELECT SUM(chT1.cnt) FROM changeTimeView chT1 WHERE TIMEDIFF(chT1.changeTime,chT2.changeTime)<=0) FROM changeTimeView chT2
Result:
2018-01-01 10:00:00 1
2018-01-01 11:00:00 2
2018-01-01 11:30:00 3
2018-01-01 12:00:00 1
2018-01-01 12:30:00 0
2018-01-01 13:30:00 1
2018-01-01 14:30:00 0
I'm currently working on a query that looks like this. There are two tables - members and member_gathering.
SELECT id, city_id, name FROM members
WHERE "id" = "member_id" IN
(
SELECT "member_id" from member_gathering
GROUP BY "member_id"
HAVING COUNT(DATEDIFF("visited","joined">=365))>=5
ORDER BY "member_id"
)
ORDER BY id*1;
The goal is to have an output of all IDs satisfying the condition of being in more than 5 groups, in which a member is active for more than a year. Being active means having a difference between "visited" and "joined" columns (both are TIMESTAMP) for more than a year (I set that as 365 days).
However, after running, this code shows all the rows in a members table (though manual check of both tables shows that some rows do not satisfy both conditions at the same time).
Any ideas on how to improve the code above? I'm not sure if I can use 'nested' condition inside COUNT(), but all other variants used before show either NULL values or returned all rows in the table, which is obviously not right. Also, I was thinking that problem might be with DATEDIFF function.
All suggestions are welcome: I'm a newbie to MySQL, so I'm not that familiar with it.
UPD: data sample:
1) members
id city_id name
2 980 Joey
5 980 Carl
10 1009 Louis
130 1092 Andrea
2) member_gathering
member_id gathering_id joined visited
2 1 2010-01-01 00:00:00 2010-02-01 00:00:00
2 2 2010-01-01 00:00:00 2010-02-01 00:00:00
5 2 2010-01-01 00:00:00 2010-02-01 00:00:00
10 3 2010-01-01 00:00:00 2010-02-01 00:00:00
130 1 2010-02-01 00:00:00 2013-02-01 00:00:00
130 2 2010-02-01 00:00:00 2013-02-01 00:00:00
130 3 2010-02-01 00:00:00 2014-02-01 00:00:00
130 4 2010-02-01 00:00:00 2018-02-01 00:00:00
130 5 2010-02-01 00:00:00 2015-02-01 00:00:00
Expected result would be only ID 130, thus: 130, 1092, Andreana.
I believe you first need to find all records where datediff is 365 days or more. Then find members who have 5 or more such instances. This needs both WHERE and HAVING clause:
SELECT id, city_id, name
FROM members
WHERE id IN (
SELECT member_id
FROM member_gathering
WHERE DATEDIFF(visited, joined) >= 365
GROUP BY member_id
HAVING COUNT(*) >= 5
)
You could use this way
SELECT id, city_id, name FROM members
WHERE member_id IN
(
SELECT member_id from member_gathering
GROUP BY member_id
HAVING SUM(DATEDIFF(visited, joined) >= 365)>=5
ORDER BY member_id
)
You should use separated expression for count differente category of datediff and remmeber that count work for not null values so if you want obtain the totale for true values you should sue SUM
I am using Mysqli
How can I do a single query that filters a subquery result? Is it possible?
I need to find users from a subquery result in a particular timestamp period.
SELECT * FROM Table WHERE (using subquery results i.e SELECT ...) BETWEEN 2017-01-08 09:00:00 AND 2017-01-08 12:00:00.
I should get back Mr A and Mr B.
Subquery results:
TimeIn User TimeOut
2017-01-06 10:00:00 Mr A 2017-01-08 11:00:00
2017-01-07 10:00:00 Mr A 2017-01-08 12:00:00
2017-01-08 10:00:00 Mr A 2017-01-08 13:00:00
2017-01-08 09:00:00 Mr B 2017-01-08 11:00:00
Thank you for your kind help as I am quite lost on how to do this.
Like this
SELECT * FROM
(
select ...
) subquery_alias_name
where timeIn BETWEEN '2017-01-08 09:00:00' AND '2017-01-08 12:00:00'
Don't forget to give the subquery an alias name
Need help for MySQL query for retrieving record of class schedule that is conflict in the given time.
Ex.
SchedID StartTime EndTime
1 09:00:00 13:00:00
2 08:30:00 10:00:00
3 11:00:00 15:00:00
4 07:30:00 08:30:00
5 11:30:00 13:00:00
I would like to retrieve the list that is conflict in this given time
Start Time = 09:00:00
End Time = 11:00:00
The record will yield following result:
SchedID StartTime EndTime
1 09:00:00 13:00:00
2 08:30:00 10:00:00
3 11:00:00 15:00:00
Thank you.
Try this
SELECT DISTINCT a.schedid, a.starttime, a.endtime
FROM
tbl_name a, tbl_name b
WHERE ((b.starttime > a.starttime AND b.starttime < a.endtime)
OR (b.endtime > a.starttime AND b.endtime < a.endtime))
ORDER BY schedid
i just found my answer here Determine Whether Two Date Ranges Overlap
Heres my query:
SELECT * FROM tableName WHERE (start_time < givenEndTime)
AND (end_time > givenStartTime);
This works perfectly fine for me.
I've a user table (MySQL) with the following data
id email creation_date
1 bob#mail.com 2011-08-01 09:00:00
2 bob#mail.com 2011-06-24 02:00:00
3 john#mail.com 2011-02-01 04:00:00
4 john#mail.com 2011-08-05 20:30:00
5 john#mail.com 2011-08-05 23:00:00
6 jill#mail.com 2011-08-01 00:00:00
As you can see we allow email duplicates so its possible to register several accounts with the same email address.
Now I need to select all adresses ordered by the creation_date but no duplicates. This is easy (i think)
SELECT * FROM (SELECT * FROM users ORDER BY creation_date) AS X GROUP BY email
Expected result:
id email creation_date
2 bob#mail.com 2011-06-24 02:00:00
6 jill#mail.com 2011-08-01 00:00:00
3 john#mail.com 2011-02-01 04:00:00
But then I also need to select all other adresses, ie. all that are not present in the result from the first query. Duplicate are allowed here.
Expected result:
id email creation_date
1 bob#mail.com 2011-08-01 09:00:00
4 john#mail.com 2011-08-05 20:30:00
5 john#mail.com 2011-08-05 23:00:00
Any ideas? Perfomance is important because the real database is very huge
SELECT * FROM a
FROM users a
LEFT JOIN (SELECT email, MIN(creation_date) as min_date GROUP BY email)x ON
(x.email = a.email AND x.min_date=a.creation_date)
WHERE x.email IS NULL
In SQL server we would do a Select statement using a rank.
Here are some MYSQL samples:
How to perform grouped ranking in MySQL
http://thinkdiff.net/mysql/how-to-get-rank-using-mysql-query/
I hope this helps.