确定重叠 DATETIME 范围的最大数量
Determine max number of overlapping DATETIME ranges
我有一个 table 有一些 DATETIME
范围,比如
id | start | end
----------------------------------------------
1 | 2011-12-18 16:00:00 | 2011-12-18 17:00:00
2 | 2011-12-19 08:00:00 | 2011-12-19 10:00:00
3 | 2011-12-19 11:00:00 | 2011-12-19 13:00:00
4 | 2011-12-19 12:00:00 | 2011-12-19 14:00:00
5 | 2011-12-19 13:00:00 | 2011-12-19 15:00:00
6 | 2011-12-19 13:00:00 | 2011-12-19 14:00:00
7 | 2011-12-20 13:00:00 | 2011-12-20 14:00:00
因此,对于 2011-12-19 日,范围跨度如下:
8 9 10 11 12 13 14 15
<-------->
<-------->
<-------->
<-------->
<---->
目标是,在插入新记录时,找到已经存在的重叠范围的最大数量:即:在插入新范围时 2011-12-19 12:00:00 - 2011-12-19 15:00:00
我想接收 3
,因为最大重叠范围数为 3,从 13:00 到 14:00.
从现在开始,我设法拥有了这个
select
count(*) as cnt
from
mytable as p
where
( # check if new renge overlap existings ones
(@start >= start and @start < end)
or
(@end > start and @end <= end)
)
or
( # check if existing range is included by new one
start between @start and @end
and
end between @start and @end
)
但是这个return4
因为它检测除了第一个之外的所有范围,但是是错误的。
我已经找到了
- Determine Whether Two Date Ranges Overlap
- How to select overlapping date ranges in SQL
- Checking a table for time overlap?
但是所有这些问题都略有不同。
我在 MysQL 5.7,但如有必要,可以升级到 8。
考虑到开始和结束永远不会相同:
select
count(*) as cnt
from
mytable as p
where
# check if new renge overlap existings ones
(@start < end and @end > start);
此答案适用于包含 window 功能的 MySQL 8.0。解决方案的核心将是以下查询,它为数据中每个有趣的区间找到多个重叠区间:
select t2.startDt, t2.endDt, count(*) overlaps_count
from
(
select lag(t1.dt) over (order by t1.dt) startDt, t1.dt endDt
from
(
select startt dt from data
union
select endt dt from data
) t1
) t2
join data on t2.startDt < data.endt and t2.endDt > data.startt
group by t2.startDt, t2.endDt
一旦你得到这个结果(我们称它为 Overlap table),那么你可以很容易地找到输入间隔的最大值,如下所示
with Overlap as
(
-- the query above
)
select max(overlaps_count)
from Overlap
where @start < endDt and @end > startDt
我有一个 table 有一些 DATETIME
范围,比如
id | start | end
----------------------------------------------
1 | 2011-12-18 16:00:00 | 2011-12-18 17:00:00
2 | 2011-12-19 08:00:00 | 2011-12-19 10:00:00
3 | 2011-12-19 11:00:00 | 2011-12-19 13:00:00
4 | 2011-12-19 12:00:00 | 2011-12-19 14:00:00
5 | 2011-12-19 13:00:00 | 2011-12-19 15:00:00
6 | 2011-12-19 13:00:00 | 2011-12-19 14:00:00
7 | 2011-12-20 13:00:00 | 2011-12-20 14:00:00
因此,对于 2011-12-19 日,范围跨度如下:
8 9 10 11 12 13 14 15
<-------->
<-------->
<-------->
<-------->
<---->
目标是,在插入新记录时,找到已经存在的重叠范围的最大数量:即:在插入新范围时 2011-12-19 12:00:00 - 2011-12-19 15:00:00
我想接收 3
,因为最大重叠范围数为 3,从 13:00 到 14:00.
从现在开始,我设法拥有了这个
select
count(*) as cnt
from
mytable as p
where
( # check if new renge overlap existings ones
(@start >= start and @start < end)
or
(@end > start and @end <= end)
)
or
( # check if existing range is included by new one
start between @start and @end
and
end between @start and @end
)
但是这个return4
因为它检测除了第一个之外的所有范围,但是是错误的。
我已经找到了
- Determine Whether Two Date Ranges Overlap
- How to select overlapping date ranges in SQL
- Checking a table for time overlap?
但是所有这些问题都略有不同。
我在 MysQL 5.7,但如有必要,可以升级到 8。
考虑到开始和结束永远不会相同:
select
count(*) as cnt
from
mytable as p
where
# check if new renge overlap existings ones
(@start < end and @end > start);
此答案适用于包含 window 功能的 MySQL 8.0。解决方案的核心将是以下查询,它为数据中每个有趣的区间找到多个重叠区间:
select t2.startDt, t2.endDt, count(*) overlaps_count
from
(
select lag(t1.dt) over (order by t1.dt) startDt, t1.dt endDt
from
(
select startt dt from data
union
select endt dt from data
) t1
) t2
join data on t2.startDt < data.endt and t2.endDt > data.startt
group by t2.startDt, t2.endDt
一旦你得到这个结果(我们称它为 Overlap table),那么你可以很容易地找到输入间隔的最大值,如下所示
with Overlap as
(
-- the query above
)
select max(overlaps_count)
from Overlap
where @start < endDt and @end > startDt