Count max overlapping reservations / bookings of a certain day - mysql

I have a table like this
id
product_id
reserved_from
reserved_till
1
1
2021-10-30 11:00:00
2021-10-30 13:00:00
2
2
2021-10-28 10:00:00
2021-10-28 12:00:00
3
2
2021-10-28 11:00:00
2021-10-28 13:00:00
4
3
2021-10-28 11:00:00
2021-10-28 13:00:00
5
2
2021-10-28 08:00:00
2021-10-28 09:00:00
6
2
2021-10-28 12:00:00
2021-10-28 16:00:00
7
2
2021-10-30 11:00:00
2021-10-30 13:00:00
8
2
2021-10-28 08:30:00
2021-10-28 09:30:00
What I want is that I get 3 as maximum counted collisions / overlaps for product_id 2 on date 2021-10-28 (id: 2,3,6 are overlapping and the max).
After researching on Google, I found severall SQL statements, but those are based on start time and end time instead of day instead on finding the maximum collisions on that day.

You can use a self-join:
select count(*) overlap from bookings b join bookings b1
on b1.product_id = b.product_id and b.id != b1.id and date(b.reserved_from) = date(b.reserved_till) and b1.reserved_till > b.reserved_from and b1.reserved_from < b.reserved_from
where b.product_id = 2 and date(b.reserved_from) = "2021-10-28"
Output:
overlap
-------
3

Related

Find rows where ID matches and date is within X days

Somewhat new to SQL and I'm running into a bit of issue with a project. I have a table like this:
ID
subscription_ID
renewal_date
1
11
2022-01-01 00:00:00
2
11
2022-01-02 00:00:00
3
12
2022-01-01 00:00:00
4
12
2022-01-01 12:00:00
5
13
2022-01-01 12:00:00
6
13
2022-01-03 12:00:00
My goal is to return rows where the subscription_ID matches and the start_date is within or equal to a certain # of days (hours would work as well). For instance, I'd like rows where subscription_ID matches and the start_date is within or equal to 1 day such that my results from the table above would be:
ID
subscription_ID
renewal_date
1
11
2022-01-01 00:00:00
2
11
2022-01-02 00:00:00
3
12
2022-01-01 00:00:00
4
12
2022-01-01 12:00:00
Any assistance would be greatly appreciated--thanks!
If I understand correctly maybe you are trying something like:
select t.*
from test_tbl t
join ( SELECT subscription_id
, MAX(diff) max_diff
FROM
( SELECT x.subscription_id
, DATEDIFF(MIN(y.start_date),x.start_date) diff
FROM test_tbl x
JOIN test_tbl y ON y.subscription_id = x.subscription_id
AND y.start_date > x.start_date
GROUP BY x.subscription_id , x.start_date
) z
GROUP BY subscription_id
) as t1 on t.subscription_id=t1.subscription_id
where t1.max_diff<=1;
Result:
id subscription_id start_date
1 11 2022-01-01 00:00:00
2 11 2022-01-02 00:00:00
3 12 2022-01-01 00:00:00
4 12 2022-01-01 12:00:00
The subquery returns:
subscription_id max_diff
11 1
12 0
13 2
which is used on the where condition.
Demo

Get dates from weekdays between 2 dates MySQL future schedule

Im trying to create a schedule table per week of year with MySQL
I have a table with the following Sample data:
employee
start_date
end_date
weekday
shift_start
shift_end
1
2021-10-01
2021-10-31
0
08:00:00
17:00:00
1
2021-10-01
2021-10-31
2
08:00:00
17:00:00
1
2021-10-01
2021-10-31
4
08:00:00
17:00:00
2
2021-10-01
2021-10-31
0
08:00:00
17:00:00
2
2021-10-01
2021-10-31
3
08:00:00
17:00:00
2
2021-10-01
2021-10-31
4
08:00:00
17:00:00
The schedule is the same every week, hence the weekday column.
I also have a calendar table for simplicity with dates for coming 2 years with the following schema:
fulldate
year
month
day
week
dayofweek
0000-00-00
0000-9999
0-11
0-30
0-53
0-6
I want to have a table output like the following for a certain weeknumber: (example week 40 of 2021)
date
employee
weekday
shift_start
shift_end
2021-10-04
1
0
08:00:00
17:00:00
2021-10-04
2
0
08:00:00
17:00:00
2021-10-06
1
2
08:00:00
17:00:00
2021-10-07
2
3
08:00:00
17:00:00
2021-10-08
1
4
08:00:00
17:00:00
2021-10-08
2
4
08:00:00
17:00:00
I have been stuck on this for a while and I haven't found a solution on the internet or made a single step in creating the table. Any help in the right direction would be greatly appreciated
Solution for your problem is:
SELECT
c.fulldate as date,
t.employee,
t.weekday,
t.shift_start,
t.shift_end
FROM calendar AS c
INNER JOIN table1 AS t
ON c.dayofweek = t.weekday
ORDER BY c.fulldate,t.employee,t.weekday
Demo Link: http://sqlfiddle.com/#!9/4c8681/4
Explanation:
Calendar table should be inner joined with input table on weekday column to get those dates for which result is required.
'WHERE' clause can be used to filter out the result as per the requirement. For example, if output is required for 40th week then use "WHERE c.week=40" in above query before 'ORDER BY' clause to get desired result.

Group By 3 columns (JobId, StartTime, EndTime) for continuous days in MySQL

I want to group by the JobId, StartTime & EndTime only for continuous days. If a specific row doesn't form part of a range it should be discarded. The Id's should also pivot into a column per grouping.
Id
Date
StartTime
EndTime
JobId
1
2021-08-23
08:30:00
19:00:00
1
2
2021-08-24
08:30:00
19:00:00
1
3
2021-08-24
12:30:00
14:30:00
2
4
2021-08-24
15:30:00
19:00:00
1
5
2021-08-25
08:30:00
19:00:00
1
6
2021-08-25
12:30:00
14:30:00
2
7
2021-08-25
15:45:00
19:00:00
1
8
2021-08-26
08:30:00
09:30:00
1
9
2021-08-26
15:30:00
19:00:00
1
10
2021-08-26
10:30:00
11:00:00
1
11
2021-08-26
12:00:00
14:30:00
1
12
2021-08-27
08:30:00
09:30:00
1
13
2021-08-27
11:00:00
11:15:00
1
14
2021-08-27
11:30:00
14:30:00
1
15
2021-08-28
08:30:00
09:30:00
1
Using the above sample data you can see 3 groupings that can form such a continuous range.
Range 1 consists of Id's, 1,2 & 5 - 2021-08-23 to 2021-08-25, 08:30:00 to 19:00:00
Range 2 consists of Id's 3 & 6 - 2021-08-24 to 2021-08-25, 12:30:00 to 14:30:00
Range 3 consists of Id's 8, 12 & 15 - 2021-08-26 to 2021-08-28, 08:30:00 to 09:30:00
The end result should be:
JobId
StartDate
EndDate
StartTime
EndTime
Ids
1
2021-08-23
2021-08-25
08:30:00
19:00:00
1,2,5
2
2021-08-24
2021-08-25
12:30:00
14:30:00
3,6
1
2021-08-26
2021-08-28
08:30:00
09:30:00
8,12,15
MySQL 8.0.23
Assuming that JobId, `Date`, StartTime, EndTime is unique you may use:
SELECT JobId,
MIN(`Date`) StartDate,
MAX(`Date`) EndDate,
StartTime,
EndTime,
GROUP_CONCAT(Id) Ids
FROM test
GROUP BY JobId,
StartTime,
EndTime
HAVING COUNT(*) > 1
AND DATEDIFF(EndDate, StartDate) = COUNT(*) - 1
ORDER BY StartDate, StartTime
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=fce8590f72ac1d50cd9e89add3ed01e7

Match between two row data

I want to select match count from result where the match count is exact int on a date.
date id_event id_timewindows max_hits
2014-12-16 1 1,2,3 2
2014-12-16 2 2,3,4 2
2014-12-16 3 4 2
2014-12-16 4 5,6 2
2014-12-16 5 7,8 2
2014-12-16 6 9 2
The result what i want is:
date id_event id_timewindows max_hits
2014-12-16 1 2,3 2
2014-12-16 2 2,3 2
Have anybody idea, how to do it in MySQL?
UPDATE:
So i have to explain more. The id_timewindows is not a string attribute, the first one is a result of a view which grouped by id_events and one id_event has multiple id_timewindow.
View result before grouped:
date id_event id_timewindow begin end max_rooms
2014-12-16 1 1 06:00:00 07:00:00 2
2014-12-16 1 2 07:00:00 08:00:00 2
2014-12-16 1 3 08:00:00 09:00:00 2
2014-12-16 2 2 07:00:00 08:00:00 2
2014-12-16 2 3 08:00:00 09:00:00 2
2014-12-16 2 4 09:00:00 10:00:00 2
2014-12-16 3 4 09:00:00 10:00:00 2
2014-12-16 4 6 11:00:00 12:00:00 2
2014-12-16 4 5 10:00:00 11:00:00 2
2014-12-16 5 7 12:00:00 13:00:00 2
2014-12-16 5 8 13:00:00 14:00:00 2
2014-12-16 6 9 14:00:00 15:00:00 2
I use GROUP BY id_event and the id_timewindows is group_concat(id_timewindow SEPARATOR ',')
I found a solution:
SELECT
date,
id_timewindow,
max_rooms,
COUNT(concat(date, id_timewindow)) as counter
FROM `timewindows_reserved`
GROUP BY
date, id_timewindow
HAVING counter < max_rooms
That will result what inverse what i want and i can use it.
date id_timewindow max_hits
2014-12-16 1 2
2014-12-16 4 2
2014-12-16 5 2
2014-12-16 6 2
2014-12-16 7 2
2014-12-16 8 2
2014-12-16 9 2
If I group by date and make a LIST from the id_timewindow then i can recevie the same result as what I wanted, but in inverse logic. Not a reserved timewindows rather the free timewindows. If I reverse this then I can get the result:
SELECT
date,
id_event,
GROUP_CONCAT(id_timewindow SEPARATOR ','),
max_rooms,
COUNT(concat(date, id_timewindow)) as counter
FROM `table`
GROUP BY
date, id_timewindow
HAVING counter >= max_rooms

SQL return last 12 weeks data, grouped by week, starting last Monday

I've been working on a MySQL query that sorts data into weeks but I just can't figure out how to do it.
I would like to sort the data into weeks for the current and last 11 weeks. Each week will run from Monday 00:00:00 to Sunday 23:59:59.
(Taking todays date as 2014-12-04)...
Week 1: 2014-12-01 > 2014-12-07 - (Last Monday 00:00:00 to next Sunday 23:59:59)
Week 2: 2014-11-24 > 2014-11-30 - (Monday before last 00:00:00 to last Sunday 23:59:59)
Week 3: 2014-11-17 > 2014-11-23 - (Monday before before last 00:00:00 to last last Sunday 23:59:59)
And so on...
For each week the value field data will be totalled.
I need the data returned to be in the format:
datetime: The first date (Always a Monday) of that week.
value: The total of all the values in that week.
For example, the returned data:
Week 1: 2014-12-01 : Totalled value=11
Week 2: 2014-11-24 : Totalled value=3
Week 3: 2014-11-17 : Totalled value=9
Week 4: 2014-11-10 : Totalled value=7
Table_1 data:
table1id datetime value
1 2014-09-01 06:00:00 4
2 2014-09-04 17:00:00 6
3 2014-09-09 18:00:00 9
4 2014-09-15 07:00:00 4
5 2014-09-20 10:00:00 2
6 2014-09-25 10:00:00 3
7 2014-09-30 09:00:00 8
8 2014-10-01 14:00:00 5
9 2014-10-05 10:00:00 7
10 2014-10-09 18:00:00 3
11 2014-10-15 05:00:00 4
12 2014-10-20 07:00:00 8
13 2014-10-24 16:00:00 9
14 2014-10-29 15:00:00 5
15 2014-10-31 16:00:00 7
16 2014-11-05 09:00:00 2
17 2014-11-10 08:00:00 4
18 2014-11-15 16:00:00 3
19 2014-11-20 10:00:00 9
20 2014-11-25 10:00:00 2
21 2014-11-30 10:00:00 1
22 2014-12-01 15:00:00 7
23 2014-12-04 18:00:00 2
I 'could' just pull all the data unsorted for the date range using PHP and sort it from there but I'd rather the MySQL server do it.
Any suggestions would be greatly appreciated. :-)
based on generate days from date range
you can do smething like that:
select mondays.week, mondays.day, sum(value)
from
(select a.a+1 week, curdate() - WEEKDAY(curdate()) - INTERVAL (7*a.a) DAY as day from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9 union all select 10 union all select 11) as a) as mondays,
Table_1
where Table_1.datetime between mondays.day and (mondays.day + interval(7) day)
group by mondays.week, mondays.day;