admin管理员组文章数量:1277896
I am trying to count number of overlapping events between dates in SQL. Let’s assume some dates for room reservations in a hotel. Like this:
start | end |
---|---|
14.01.2024 | 17.01.2024 |
15.01.2024 | 17.01.2024 |
17.01.2024 | 19.01.2024 |
I am trying to count number of overlapping events between dates in SQL. Let’s assume some dates for room reservations in a hotel. Like this:
start | end |
---|---|
14.01.2024 | 17.01.2024 |
15.01.2024 | 17.01.2024 |
17.01.2024 | 19.01.2024 |
I need to find how many rooms are booked every day (the checkout date is included). In my case it should be:
date | No of rooms |
---|---|
14.01.2024 | 1 |
15.01.2024 | 2 |
16.01.2024 | 2 |
17.01.2024 | 3 |
18.01.2024 | 1 |
19.01.2024 | 1 |
I can generate time series of a given range (14.01 – 19.01 in this case) and join it to the data, but I am allowed to work only with a singe table. So, what I have to work with is:
time_series | start | end |
---|---|---|
14.01.2024 | 14.01.2024 | 17.01.2024 |
15.01.2024 | 15.01.2024 | 17.01.2024 |
16.01.2024 | null | null |
17.01.2024 | 17.01.2024 | 19.01.2024 |
18.01.2024 | null | null |
19.01.2024 | null | null |
I am looking for a select query that will take every value of the time_series column and count rows which have this date between start and end (end is included). Is there any way to do this with a sort of common table expression?
Share Improve this question asked Feb 24 at 20:53 AstAAstA 111 bronze badge 4 |2 Answers
Reset to default 1It's not entirely clear what your "use only one table" restriction means.
Let's say you somehow got this table
date_series
:
time_series | start_date | end_date |
---|---|---|
2024-01-14 | 2024-01-14 | 2024-01-17 |
2024-01-15 | 2024-01-15 | 2024-01-17 |
2024-01-16 | null | null |
2024-01-17 | 2024-01-17 | 2024-01-19 |
2024-01-18 | null | null |
2024-01-19 | null | null |
Using this table, count by self JOIN date_series
.
We take DISTINCT time_series
for case where several reservations have same date.
select t1.time_series,count(t2.start_date) as No_of_rooms
from (select distinct time_series from date_series) as t1
left join date_series t2 on t1.time_series between t2.start_date and t2.end_date
group by t1.time_series
time_series | No_of_rooms |
---|---|
2024-01-14 | 1 |
2024-01-15 | 2 |
2024-01-16 | 2 |
2024-01-17 | 3 |
2024-01-18 | 1 |
2024-01-19 | 1 |
fiddle
A more common way to solve such a problem
- Generate date_range. In this example by recursive query. More examples see reference in @JNevill comment.
- Join source table with date_range, then count(start_date) thru GROUP BY.
See exmple
with recursive date_range as(
select cast('2024.01.14' as date) as report_date, cast('2024.01.19' as date) to_date
union all
select date_add(report_date,interval 1 day), to_date
from date_range
where report_date<to_date
)
select report_date,count(start_date) as No_of_rooms
from date_range d
left join reservations r on d.report_date between r.start_date and r.end_date
group by report_date
report_date | No_of_rooms |
---|---|
2024-01-14 | 1 |
2024-01-15 | 2 |
2024-01-16 | 2 |
2024-01-17 | 3 |
2024-01-18 | 1 |
2024-01-19 | 1 |
fiddle
Your intermediate table somewhat is the dump of what you would have got from a CTE.
Joining the table to itself, by considering only the first column in its first (left) use, and only the last two columns on the right side, will emulate the two original tables.
select t.time_series, count(1) no_of_rooms
from ts t join ts f on t.time_series between f.start and f.end
group by t.time_series
order by t.time_series;
See it in a fiddle.
Note that the comparison to the null
-valued columns of the right side will naturally discard rows for that second table when the row has only a first table use (e.g. the 16.01 which is not a booking occurrence but only a series date).
Handling of same-date bookings
Note that this solution entirely relies on the careful building of your intermediate table.
In particular when two bookings start as the same date only one should get a valued time_series
, the other one shall have a null
in that column.
See a fiddle with another booking to illustrate that.
IMHO
That "only one table" requirement looks suspicious, because it complicates everything and essentially forces to recompose (deduce) the original table + the series from your intermediate table.
On the contrary, the requirement may be a way to force you to not create another, intermediate table, to direct you to a full-CTE solution (including the series generation):
instead of create table series_and_bookings as select …; select [final query];
it would like to incite you to write with series_and_bookings as (select …) select [final query];
.
Really we can say that it doesn't add a table (in case of a crash a CTE won't let artifacts, which I think is the real requirement).
Thus you may want to challenge the requirement, at least ask for a clarification.
本文标签: mysqlcount how many event between dates sql in different rowsStack Overflow
版权声明:本文标题:mysql - count how many event between dates sql in different rows - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741241984a2364159.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
BETWEEN start AND end
in theON
condition. – Barmar Commented Feb 24 at 21:04