确定重叠 DATETIME 范围的最大数量

fud*_*udo 4 mysql sql datetime range overlap

我有一张有一些范围的桌子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
Run Code Online (Sandbox Code Playgroud)

因此,2011 年 12 月 19 日的范围如下:

8    9   10   11   12   13   14   15
<-------->
               <-------->
                    <-------->
                         <-------->
                         <---->
Run Code Online (Sandbox Code Playgroud)

目标是,在插入新记录时,找到已存在的重叠范围的最大数量:即:在插入新范围时,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
    )
Run Code Online (Sandbox Code Playgroud)

但是这个返回是4因为它检测到除第一个范围之外的所有范围,但这是错误的。

我已经找到了

但所有这些问题都略有不同。

我使用的是 Mysql 5.7,但如果需要的话可以升级到 8。

Rad*_*ača 6

这个答案适用于包含窗口函数的 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
Run Code Online (Sandbox Code Playgroud)

数据库小提琴演示

一旦获得此结果(我们称之为重叠表),您就可以轻松找到输入间隔的最大值,如下所示

with Overlap as
(
   -- the query above
)
select max(overlaps_count)
from Overlap 
where @start < endDt and @end > startDt
Run Code Online (Sandbox Code Playgroud)