如何在MySQL中找到与一组小时重叠的事件范围?

时间:2011-10-24 21:44:09

标签: mysql datetime

假设我有一个名为events的表,其中包含列

INT  id
DATETIME start_time
DATETIME end_time

如何查找从start_time到end_time的任何时间范围内的所有行都在特定小时范围内?

例如,我可能希望在8-10pm小时范围内找到事件占其中一部分的行。

这样的东西
select * from events where (hour(start_time) IN (20, 21, 22)) or (hour(end_time) IN (20, 21, 22))
除了在晚上8点之前开始并在晚上11点之后结束的事件之外,

会起作用。

最后,它必须跨越日界,所以23-2(晚上11点 - 凌晨2点)的范围也应该有效。

不幸的是我无法修改表的架构。

2 个答案:

答案 0 :(得分:2)

假设start_time和end_time字段是datetime字段,那么

SELECT *
FROM events
WHERE (start_time <= $event_end_time) AND (end_time >= $event_start_time)

这有点违反直觉,但如果你在时间轴上看一下:

A&amp; B是你的极限fenceposts。 X&amp; Y是start_time和end_time字段:

         A   B
p = -----------   event falls outside the boundaries
     X Y

         A    B
q = -----------   partial overlap
     X    Y

       A   B
r = -----------   partial overlap again
        X    Y

       A   B
s = -----------  full overlap
     X       Y

      A  B
t = -----------  outside boundaries
           X Y

你对Q,R和S的情况感兴趣。你会注意到,对于这3个案例,Y总是&gt; = A,而X总是&lt; = B

答案 1 :(得分:1)

我设法使用日边界要求来完成这项工作。这很难看,但似乎涵盖了所有情况。

虽然您可以编写存储过程来执行此操作,但在Java中表达更容易,因此:

public void checkEvents (int[][] events, int startHour, int endHour)    

  final int START         = 0;
  final int END           = 1;
  final int HOURS_PER_DAY = 24;

  for (int[] event : events) {

    int start = startHour;
    int end = (endHour < startHour) ? endHour + HOURS_PER_DAY : endHour;

    int eventStart = event[START];
    int eventEnd = (event[END] < event[START]) ? event[END] + HOURS_PER_DAY : event[END];

    if (checkOverlap(result, event, start, end, eventStart, eventEnd))
    || (checkOverlap(result, event, start, end, eventStart + HOURS_PER_DAY, eventEnd + HOURS_PER_DAY))
      || (checkOverlap(result, event, start + HOURS_PER_DAY, end + HOURS_PER_DAY, eventStart, eventEnd))
       || (!checkOverlap(result, event, start + HOURS_PER_DAY, end + HOURS_PER_DAY, eventStart + HOURS_PER_DAY, eventEnd + HOURS_PER_DAY);
          System.out.println("overlapped!");
  }
}

private boolean checkOverlap(ArrayList<int[]> result, int[] event, int start, int end, int eventStart, int eventEnd) {

  if ((eventStart >= start && eventStart < end) || (eventStart < start && eventEnd > start)) {
    return true;
  }

  return false;
}