我一直在思考如何简化这里提出的问题. 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