检查MySQL中date范围的重叠

此表用于存储会话(事件):

CREATE TABLE session ( id int(11) NOT NULL AUTO_INCREMENT , start_date date , end_date date ); INSERT INTO session (start_date, end_date) VALUES ("2010-01-01", "2010-01-10") , ("2010-01-20", "2010-01-30") , ("2010-02-01", "2010-02-15") ; 

我们不想在范围之间有冲突。
假设我们需要在2010-01-052010-01-25之间插入一个新的会话。
我们想知道有冲突的会议。

这是我的查询:

 SELECT * FROM session WHERE "2010-01-05" BETWEEN start_date AND end_date OR "2010-01-25" BETWEEN start_date AND end_date OR "2010-01-05" >= start_date AND "2010-01-25" <= end_date ; 

结果如下:

 +----+------------+------------+ | id | start_date | end_date | +----+------------+------------+ | 1 | 2010-01-01 | 2010-01-10 | | 2 | 2010-01-20 | 2010-01-30 | +----+------------+------------+ 

有没有更好的方法来获得?


小提琴

我有一个我曾经写过的日历应用程序的查询。 我想我用了这样的东西:

 ... WHERE new_start < existing_end AND new_end > existing_start; 

更新这应该肯定工作((ns,ne,es,ee)=(new_start,new_end,existing_start,existing_end)):

  1. ns – ne – es – ee:不重叠并且不匹配(因为ne <es)
  2. ns – es – nee ee:重叠和匹配
  3. es – ns – ee – ne:重叠和匹配
  4. es – ee – ns – ne:不重叠,不匹配(因为ns> ee)
  5. es – ns – neeee:重叠和匹配
  6. ns – es – ee – ne:重叠和匹配

这是一个小提琴

 SELECT * FROM tbl WHERE existing_start BETWEEN $newStart AND $newEnd OR existing_end BETWEEN $newStart AND $newEnd OR $newStart BETWEEN existing_start AND existing_end if (!empty($result)) throw new Exception('We have overlapping') 

这3行sql语句覆盖了需要重叠的4种情况。

拉米的答案是好的,但是你可以优化一点。

 SELECT * FROM tbl WHERE existing_start BETWEEN $newSTart AND $newEnd OR $newStart BETWEEN existing_start AND existing_end 

这将捕捉范围重叠的所有四种情况,并排除两者不相同的情况。

我遇到了类似的问题。 我的问题是停止预定的date范围之间。 例如,5月2日至7date间,预订将被禁止入住。 我需要find任何重叠的date来检测和停止预订。 我的解决scheme与LordJavac类似。

 SELECT * FROM ib_master_blocked_dates WHERE venue_id=$venue_id AND ( (mbd_from_date BETWEEN '$from_date' AND '$to_date') OR (mbd_to_date BETWEEN '$from_date' AND '$to_date') OR ('$from_date' BETWEEN mbd_from_date AND mbd_to_date) OR ('$to_date' BETWEEN mbd_from_date AND mbd_to_date) ) *mbd=master_blocked_dates 

让我知道如果它不起作用。

给定两个区间如(s1,e1)和(s2,e2),其中s1 <e1和s2 <e2
你可以像这样计算重叠:

 SELECT s1, e1, s2, e2, ABS(e1-s1) as len1, ABS(e2-s2) as len2, GREATEST(LEAST(e1, e2) - GREATEST(s1, s2), 0)>0 as overlaps, GREATEST(LEAST(e1, e2) - GREATEST(s1, s2), 0) as overlap_length FROM test_intervals 

如果一个间隔在另一个间隔内,也可以工作。

最近,我在同一个问题上挣扎,并以这一个简单的步骤结束(这可能不是一个好方法或内存消耗) –

 SELECT * FROM duty_register WHERE employee = '2' AND ( ( duty_start_date BETWEEN {$start_date} AND {$end_date} OR duty_end_date BETWEEN {$start_date} AND {$end_date} ) OR ( {$start_date} BETWEEN duty_start_date AND duty_end_date OR {$end_date} BETWEEN duty_start_date AND duty_end_date) ); 

这帮助我find重叠date范围的条目。

希望这有助于某人。