检查新间隔是否重叠 – MySQL(或PHP)

我一直在思考如何简化这里提出的问题.
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]不与任何其他区间重叠.考虑因素:

>是的,我可以将整个表拉成一个数组并对其进行O(N)搜索.那很无聊.
>我更喜欢在MySQL中执行此操作,因此我不必每次都删除可能是任意大的表.

请参见下图.这表示可以插入和不插入的边界. http://i.stack.imgur.com/jE59w.png

最佳答案 使用以下缩写:

> [old]:=现有范围
> [new]:=插入范围
> OS:=(旧)existing_range.start
> OE:=(旧)existing_range.end
> NS:=(new)insertion_range.start
> NE:=(new)insertion_range.end

两个范围(旧的和新的)重叠的条件是:(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
点赞