Как найти диапазоны событий, перекрывающие набор часов в MySQL? - PullRequest
0 голосов
/ 25 октября 2011

Предполагая, что у меня есть таблица с именем events со столбцами

INT  id
DATETIME start_time
DATETIME end_time

как бы найти все строки, где любая часть временного диапазона от start_time до end_time попадает в определенный часовой диапазон?

Например, я могу захотеть найти строки, в которых события имели некоторую их часть в течение 8-10 часов вечера.

Что-то вроде

select * from events where (hour(start_time) IN (20, 21, 22)) or (hour(end_time) IN (20, 21, 22))

будет работать, за исключением событий, которые начались до 8 вечера и закончились после 11 вечера. * 10101 *

Наконец, он должен работать за пределами дневных границ, поэтому диапазон, например, 23-2 (23:00 - 2:00), также должен работать.

К сожалению, я не могу изменить схему таблицы.

Ответы [ 2 ]

2 голосов
/ 25 октября 2011

Предполагая, что поля start_time и end_time являются полями datetime, тогда

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

Это немного нелогично, но если вы посмотрите на это на временной шкале:

A & B - ваши предельные значения для забора.X & 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. Вы заметите, что для этих трех случаев Y ВСЕГДА> = A, а X -всегда <= B </p>

1 голос
/ 16 ноября 2011

Мне удалось сделать эту работу с требованием границ дня. Это некрасиво, но, похоже, охватывает все дела.

Хотя вы можете написать для этого хранимую процедуру, это проще выразить на 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...