Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Перекрывающиеся даты MySQL, не конфликтующие

Автор вопроса: RobОтветов: 5

Я видел много тем о диапазонах дат в MySQL, но я все еще не могу найти ответ на то, что я ищу, поэтому любая помощь будет принята с благодарностью.

У меня есть таблица MySQL с 3 столбцами, дата - время начала - время окончания. Дата является полем типа "дата" MySQL, а время начала и окончания являются полями типа "время".

Скажем, например, у меня есть запись в базе данных следующим образом, давайте назовем эту сессию 1;

date = 2011-06-30, startTime = 09:00:00, finishTime = 11:00:00

Если я приду, чтобы добавить еще один сеанс, мне нужно убедиться, что он не конфликтует с существующим сеансом. Таким образом, следующее не удастся, потому что оно попадает между временем начала и окончания сеанса 1.

date = 2011-06-30, startTime = 10:00:00, finishTime = 12:00:00

Таким образом, запись может быть вставлена ​​только "ПОСЛЕ" или "ДО" существующей сессии.

Я использую PHP/MySQL и исхожу из того, что запрос может быть запущен, и если есть совпадающие результаты, то произойдет сбой, если нет совпадающих результатов, затем вставьте.

Заранее спасибо.

  • И что происходит, когда есть сессия с 09:00 - 11:00, а новый - 11:00 - 13:00. Столкновение или нет? ypercubeᵀᴹ 29.06.2011
  • @Rob: Тогда решения BETWEEN не будут работать, так как они приведут к столкновению. ypercubeᵀᴹ 01.07.2011

phpdaterangeoverlapping

Ответы

Ответ 1 · рейтинг 4 · Hammerite

Я использую PHP/MySQL и исхожу из того, что запрос может быть запущен, и если есть совпадающие результаты, то ошибка, если нет совпадающих результатов, тогда вставка.

Что ж, попробуй это. Здесь :date: - это дата записи, которую вы собираетесь добавить, а :start-time: и :finish-time: - время ее начала и окончания соответственно.

SELECT EXISTS (
    SELECT
        1
    FROM
        TableName
    WHERE
        `date` = :date: AND
        ( :start-time: BETWEEN startTime AND finishTime OR
          :finish-time: BETWEEN startTime AND finishTime OR
          startTime BETWEEN :start-time: AND :finish-time:
          )
) AS `Clash`

Ответ 2 · рейтинг 1 · emont01

Я столкнулся с этой проблемой обнаружения перекрытия дат, моя первая идея состояла в том, чтобы сделать что-то вроде решения Hammerite, но я нашел это решение неполным, главным образом потому, что существует слишком много возможных сценариев, когда два диапазона дат могут конфликтовать:

Запрос, который я использовал для решения этой проблемы, был примерно таким:

/* overlapping dates */
SELECT *
FROM my_table
WHERE `date` = $date AND
  NOT (
    `start_time` < $start_time and `finish_time` < $start_time
    OR
    `start_time` > $end_time and `finish_time` > $end_time
  )

Для получения более подробной информации вы можете посетить мой блог здесь

Ответ 3 · Michael J.V.

Я бы по-другому структурировал таблицу. У меня было бы два столбца, оба типа datetime, с именами session_start и session_end.

Логика такова: вы не можете вставить новую сессию, если ее session_start время не > или <, чем старая сессия session_end.

Ответ 4 · Abhay

Предполагая, что $date, $startTime и $finishTime являются вашими переменными PHP, которые хранят дату, время начала и время окончания соответственно для вставки.

$query = 'INSERT INTO `session`
SELECT \'' . $date . '\', \'' . $startTime . '\', \'' . $finishTime . '\'
FROM `session`
WHERE NOT EXISTS (SELECT *
    FROM `session`
    WHERE `date` = \'' . $date . '\'
    AND \'' . $startTime . '\' BETWEEN `startTime` and `finishTime`
)';

Надеюсь это поможет.

Ответ 5 · ypercubeᵀᴹ

Я бы использовал простой:

INSERT INTO session
  ( `date`, startTime, finishTime )
  SELECT
  ( $date, $startTime, $finishTime )
  WHERE NOT EXISTS
    ( SELECT
          *
      FROM
          session
      WHERE
            `date` = $date
        AND $startTime <  finishTime
        AND  startTime < $finishTime

    )

< следует изменить на <=, если вы хотите, чтобы два периода 09:00 - 11:00 и 11:00 - 13:00 совпадали.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы