Эй, я наткнулся на этот сайт в поисках решений для перекрытия событий в таблицах mySQL. Я был НАСТОЛЬКО впечатлен решением (которое уже помогает), я подумал, что посмотрю, смогу ли я получить дополнительную помощь...
Итак, Джо хочет поменяться сменами с кем-нибудь на работе. У него дата суда. Он идет к форме обмена сменами, и она показывает расписание на эту неделю (или то, что от него осталось). Это делается с помощью запроса к БД. Нет пота. Он выбирает смену. С этого момента он становится колючим.
Итак, сначала форма передает скрипту начало и конец смены. Он выполняет запрос для всех, у кого есть смена, перекрывающая эту смену. Они не могут работать в две смены сразу, поэтому все ID пользователей из этого запроса заносятся в черный список. Этот запрос выглядит так:
SELECT DISTINCT user_id FROM shifts
WHERE
FROM_UNIXTIME('$swap_shift_start') < shiftend
AND FROM_UNIXTIME('$swap_shift_end') > shiftstart
Затем мы запускаем запрос для всех смен, которые а) имеют одинаковую продолжительность (политика компании) и б) не пересекаются ни с какими другими сменами, в которых работает Джо.
В настоящее время у меня есть что-то вроде этого:
SELECT *
FROM shifts
AND shiftstart BETWEEN FROM_UNIXTIME('$startday') AND FROM_UNIXTIME('$endday')
AND user_id NOT IN ($busy_users)
AND (TIME_TO_SEC(TIMEDIFF(shiftend,shiftstart)) = '$swap_shift_length')
$conflict_dates
ORDER BY shiftstart, lastname
Теперь вы, вероятно, задаетесь вопросом: «Что такое $conflict_dates???».
Что ж, когда Джо отправляет сменную смену, он перезагружает его смены на неделю на случай, если он решит проверить потенциал другой смены. Поэтому, когда он выполняет этот первый запрос, в то время как скрипт перебирает и выводит его варианты, он также создает строку, которая выглядит примерно так:
AND NOT(
'joe_shift1_start' < shiftend
AND 'joe_shift1_end' > shiftstart)
AND NOT(
'joe_shift2_start' < shiftend
AND 'joe_shift2_end' > shiftstart)
...etc
Так что база данных получает довольно длинный запрос по строкам:
SELECT *
FROM shifts
AND shiftstart BETWEEN FROM_UNIXTIME('$startday') AND FROM_UNIXTIME('$endday')
AND user_id NOT IN ('blacklisteduser1', 'blacklisteduser2',...etc)
AND (TIME_TO_SEC(TIMEDIFF(shiftend,shiftstart)) = '$swap_shift_length')
AND NOT(
'joe_shift1_start' < shiftend
AND 'joe_shift1_end' > shiftstart)
AND NOT(
'joe_shift2_start' < shiftend
AND 'joe_shift2_end' > shiftstart)
AND NOT(
'joe_shift3_start' < shiftend
AND 'joe_shift3_end' > shiftstart)
AND NOT(
'joe_shift4_start' < shiftend
AND 'joe_shift4_end' > shiftstart)
...etc
ORDER BY shiftstart, lastname
Итак, я надеюсь, что либо в SQL есть какой-то гениальный способ справиться с этим более простым способом, либо кто-то может указать фантастический логический принцип, который гораздо умнее объясняет потенциальные конфликты. (Обратите внимание на использование «начало> конец, конец ‹ начало», прежде чем я обнаружил, что использую промежутки и должен был вычесть минуту с обоих концов.)
Спасибо!
A