Определите максимальное количество перекрывающихся диапазонов DATETIME - PullRequest
0 голосов
/ 11 декабря 2018

У меня есть таблица с некоторыми 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
    )

Но это возвращение 4, поскольку оно обнаруживает все диапазоны, кроме первого, но неверно.

Я уже нашел

Но все эти вопросы немного отличаются.

Я на MysQL 5.7, но обновляюсь до 8возможно при необходимости.

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

Этот ответ для 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

DBFiddle DEMO

Получив этот результат (пусть назовем его таблицей перекрытий), вы можете легко найти максимум для входного интервала следующим образом:

with Overlap as
(
   -- the query above
)
select max(overlaps_count)
from Overlap 
where @start < endDt and @end > startDt
0 голосов
/ 11 декабря 2018

Учитывая, что начало и конец никогда не будут одинаковыми:

select
    count(*) as cnt
from
    mytable as p
where
    # check if new renge overlap existings ones
        (@start < end and @end > start);
...