如何按每分钟的时间间隔计算 sql 中的并发预订?
How to count concurrently bookings in sql in time interval per minute?
如果我有一个预订的开始和结束时间,我如何计算每分钟的预订数量?我制作了我的数据库的简化版本 table 如下所示:
Start time | End time | booking |
--------------------------------------------------
2020-09-01 10:00 | 2020-09-01 10:10 | Booking 1 |
2020-09-01 10:00 | 2020-09-01 10:05 | Booking 2 |
2020-09-01 10:05 | 2020-09-01 10:10 | Booking 3 |
2020-09-01 10:09 | 2020-09-01 10:10 | Booking 4 |
我想在给定的时间间隔之间进行预订,例如 10:02 - 10:09。结果应该是这样的:
想要的结果
Time | count
-----------
10:02 | 2 |
10:03 | 2 |
10:04 | 2 |
10:05 | 3 |
10:06 | 2 |
10:07 | 2 |
10:08 | 2 |
10:09 | 3 |
问题
如何实现?今天我把它导出到 python 但是我认为应该可以直接在 SQL.
中实现
您可以使用递归查询生成时间戳范围,然后反转 table 并加入:
with recursive dates (ts) as(
select '2020-09-01'
union all
select ts + interval 1 minute
from dates
where ts + itnerval 1 minute < '2020-09-02'
)
select d.ts, sum(t.cnt) over(order by d.ts) cnt
from dates d
left join (
select start_time ts, 1 cnt from mytable
union all select end_time, -1 from mytable
) t on t.ts <= d.ts
如果您打算 运行 在较长的时间段内重复 and/or,最好在日历 table 中具体化日期范围,而不是使用递归查询。日历 table 在很长一段时间内每分钟有一行 - 假设 table 称为 date_calendar
,你会这样做:
select d.ts, sum(t.cnt) over(order by d.ts) cnt
from date_calendar d
left join (
select start_time ts, 1 cnt from mytable
union all select end_time, -1 from mytable
) t on t.ts <= d.ts
where d.ts >= '2020-09-01' and d.ts < '2020-09-02'
您可以直接对您的数据使用递归 CTE:
with recursive cte as (
select start_time, end_time
from t
union all
select start_time + interval 1 minute, end_time
from cte
where start_time < end_time
)
select start_time, count(*)
from cte
group by start_time
order by start_time;
Here 是一个 db<>fiddle.
编辑:
在 MySQL 的早期版本中,有一个计数 table 会有所帮助。您可以使用类似以下内容即时创建一个:
(select @rn := @rn + 1 as n
from t cross join
(select @rn := 0) params
) tally
您的最大跨度需要足够的数字,但您可以这样做:
select t.start_time + interval tally.n hour, count(*)
from t join
(select @rn := @rn + 1 as n
from t cross join
(select @rn := -1) params -- so it starts from 0
limit 100
) tally
on t.start_time + interval tally.n hour <= t.end_time
group by t.start_time + interval tally.n hour;
如果我有一个预订的开始和结束时间,我如何计算每分钟的预订数量?我制作了我的数据库的简化版本 table 如下所示:
Start time | End time | booking |
--------------------------------------------------
2020-09-01 10:00 | 2020-09-01 10:10 | Booking 1 |
2020-09-01 10:00 | 2020-09-01 10:05 | Booking 2 |
2020-09-01 10:05 | 2020-09-01 10:10 | Booking 3 |
2020-09-01 10:09 | 2020-09-01 10:10 | Booking 4 |
我想在给定的时间间隔之间进行预订,例如 10:02 - 10:09。结果应该是这样的:
想要的结果
Time | count
-----------
10:02 | 2 |
10:03 | 2 |
10:04 | 2 |
10:05 | 3 |
10:06 | 2 |
10:07 | 2 |
10:08 | 2 |
10:09 | 3 |
问题
如何实现?今天我把它导出到 python 但是我认为应该可以直接在 SQL.
中实现您可以使用递归查询生成时间戳范围,然后反转 table 并加入:
with recursive dates (ts) as(
select '2020-09-01'
union all
select ts + interval 1 minute
from dates
where ts + itnerval 1 minute < '2020-09-02'
)
select d.ts, sum(t.cnt) over(order by d.ts) cnt
from dates d
left join (
select start_time ts, 1 cnt from mytable
union all select end_time, -1 from mytable
) t on t.ts <= d.ts
如果您打算 运行 在较长的时间段内重复 and/or,最好在日历 table 中具体化日期范围,而不是使用递归查询。日历 table 在很长一段时间内每分钟有一行 - 假设 table 称为 date_calendar
,你会这样做:
select d.ts, sum(t.cnt) over(order by d.ts) cnt
from date_calendar d
left join (
select start_time ts, 1 cnt from mytable
union all select end_time, -1 from mytable
) t on t.ts <= d.ts
where d.ts >= '2020-09-01' and d.ts < '2020-09-02'
您可以直接对您的数据使用递归 CTE:
with recursive cte as (
select start_time, end_time
from t
union all
select start_time + interval 1 minute, end_time
from cte
where start_time < end_time
)
select start_time, count(*)
from cte
group by start_time
order by start_time;
Here 是一个 db<>fiddle.
编辑:
在 MySQL 的早期版本中,有一个计数 table 会有所帮助。您可以使用类似以下内容即时创建一个:
(select @rn := @rn + 1 as n
from t cross join
(select @rn := 0) params
) tally
您的最大跨度需要足够的数字,但您可以这样做:
select t.start_time + interval tally.n hour, count(*)
from t join
(select @rn := @rn + 1 as n
from t cross join
(select @rn := -1) params -- so it starts from 0
limit 100
) tally
on t.start_time + interval tally.n hour <= t.end_time
group by t.start_time + interval tally.n hour;