我一直在考虑如何简化此处提出的问题。 Complex MySQL Query - Checking for overlapping DATE intervals
在它的核心,减去DATES所有奇特的魔力,这只是检查重叠间隔的问题。所有日期都可以被认为是数字,它可以使逻辑更容易。想象一下下表:
Schedules
schedule_id | start | end
1 | 1 | 3
2 | 4 | 7
3 | 8 | 13
4 | 15 | 16
5 | 18 | 24
6 | 25 | 28
我正在尝试插入一个新的间隔,使[a,b]不与任何其他间隔重叠。考虑因素:
请参见下图。这表示可以插入和不插入的边界。 http://i.stack.imgur.com/jE59w.png
答案 0 :(得分:2)
使用以下缩写:
两个范围(旧的和新的)重叠的条件是:(OS < NE) AND (OE > NS)
虽然解决方案可能并非微不足道,但实现目标并不困难:
如果新范围完全在现有范围之前或之后,则没有重叠:[new] <= [old] OR [old] <= [new]
这意味着:
(NE <= OS) OR (OE <= NS)
谈判这个陈述,我们得到重叠的条件:
!( (NE <= OS) OR (OE <= NS) )
现在使用De Morgan's law我们可以将其写为
!(NE <= OS) AND !(OE <= NS)
这相当于
(NE > OS) AND (OE > NS)
可以重写为
(OS < NE) AND (OE > NS)
现在我们可以使用找到所有重叠范围
SELECT o.*
FROM Schedules o
WHERE o.start < :new_end
AND o.end > :new_start
答案 1 :(得分:0)
您可以将插入标记为:
insert into schedules(start, end)
select s, e
from (select $start s, $end as e) t
where not exists (select 1
from schedules s2
where s.start <= t.end and s.end >= t.start
);
如果该值与表中的现有行不重叠,则只会插入该值。