Сравнение нескольких дат в MySQL - PullRequest
2 голосов
/ 20 апреля 2011

Мы работаем над системой бронирования, которая должна поддерживать раздельные встречи.У этих встреч есть первая половина, перерыв, во время которого можно заказать что-то еще, а затем вторая половина.

Система также поддерживает обычные бронирования со стандартным началом и концом.

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

Раньше мы делали это в PHP, но в этой ситуации нужно делать это исключительно в mysql.

таблица заказов имеет:

startDate (всегда) splitStartDate (иногда)splitEndDate (иногда) endDate (всегда)

Когда splitStartDate и splitEndDate не используются для бронирования, они имеют значение 0000-00-00 00: 00: 00

Мы начали пытатьсячтобы построить выражение mysql из ifs, но оно кажется смехотворно длинным.

    "SELECT *
     FROM bookings WHERE
    (
        (
            IF(
                splitStartDate != "0000 00:00:00",
                IF(
                    ((CONVERT_TZ('" . $requested_start_time->format("Y-m-d G:i:s") . "', \"$tzone\", \"UTC\") >= startDate) AND (CONVERT_TZ('" . $requested_start_time->format("Y-m-d G:i:s") . "', \"$tzone\", \"UTC\") < splitStartDate))
                    OR
                    ((CONVERT_TZ('" . $requested_start_time->format("Y-m-d G:i:s") . "', \"$tzone\", \"UTC\") >= splitEndDate) AND (CONVERT_TZ('" . $requested_start_time->format("Y-m-d G:i:s") . "', \"$tzone\", \"UTC\") < endDate))
                    , 1, 0
                ),
                IF(
                    (CONVERT_TZ('" . $requested_start_time->format("Y-m-d G:i:s") . "', \"$tzone\", \"UTC\") < endDate) AND (CONVERT_TZ('" . $requested_start_time->format("Y-m-d G:i:s") . "', \"$tzone\", \"UTC\") >= startDate), 1, 0        
                )
            ) = 1
        )
        OR
        (
            IF(
                splitStartDate != "0000-00-00 00:00:00",
                IF(
                    ((CONVERT_TZ('" . $requested_end_time->format("Y-m-d G:i:s") . "', \"$tzone\", \"UTC\") > startDate) AND (CONVERT_TZ('" . $requested_end_time->format("Y-m-d G:i:s") . "', \"$tzone\", \"UTC\") <= splitStartDate))
                    OR
                    ((CONVERT_TZ('" . $requested_end_time->format("Y-m-d G:i:s") . "', \"$tzone\", \"UTC\") > splitEndDate) AND (CONVERT_TZ('" . $requested_end_time->format("Y-m-d G:i:s") . "', \"$tzone\", \"UTC\") <= endDate))
                    , 1, 0
                ),
                IF(
                    (CONVERT_TZ('" . $requested_end_time->format("Y-m-d G:i:s") . "', \"$tzone\", \"UTC\") > startDate) AND (CONVERT_TZ('" . $requested_end_time->format("Y-m-d G:i:s") . "', \"$tzone\", \"UTC\") <= endDate), 1, 0        
                )
            ) = 1           
        )
        OR 
        (

Мы знаем, что должен быть гораздо более простой способ сделать это, но мы были озадачены тем, что это такое.Мы будем рады любым предложениям о том, как построить запрос mysql для этого.

При проверке доступности мы выполняли следующие проверки (извините за то, как долго это происходит, но это проблема):

------------
all simple

requested startDate is in-between existing startDate and existing endDate
requested endDate is in-between existing startDate and existing endDate
existing startDate is in-between requested startDate and requested endDate
existing endDate is in-between requested startDate and requested endDate



-------------
advanced desired / simple existing

requested startDate is in-between existing startDate and existing endDate
requested splitStartDate is in-between existing startDate and existing endDate
existing startDate is in-between requested startDate and requested splitStartDate
existing endDate is in-between requested startDate and requested splitStartDate

requested splitEndDate is in-between existing startDate and existing endDate
requested endDate is in-between existing startDate and existing endDate
existing startDate is in-between requested splitEndDate and requested endDate
existing endDate is in-between requested splitEndDate and requested endDate


------
simple desired / advanced existing

requested startDate is in-between existing startDate and existing splitstartDate
requested endDate is in-between existing startDate and existing splitstartDate
existing startDate is in-between requested startDate and requested endDate
existing splitstartDate is in-between requested startDate and requested endDate

requested startDate is in-between existing splitEndDate and existing endDate
requested endDate is in-between existing splitEndDate and existing endDate
existing splitEndDate is in-between requested startDate and requested endDate
existing endDate is in-between requested startDate and requested endDate

-----
advanced both

1st 1/2 both
requested startDate is in-between existing startDate and existing splitstartDate
requested splitStartDate  is in-between existing startDate and existing splitstartDate
existing startDate is in-between requested startDate and requested splitStartDate
existing splitstartDate  is in-between requested startDate and requested splitStartDate

2/2 desired  1/2 existing
requested splitEndDate  is in-between existing startDate and existing splitstartDate
requested endDate is in-between existing startDate and existing splitstartDate
existing startDate is in-between requested splitEndDate and requested endDate
existing splitstartDate is in-between requested splitEndDate and requested endDate

1/2 desired 2/2 existing
requested startDate is in-between existing splitEndDate and existing endDate
requested splitStartDate  is in-between existing splitEndDate and existing endDate
existing splitEndDate  is in-between requested startDate and requested splitStartDate
existing endDate is in-between requested startDate and requested splitStartDate

2nd 1/2 all
requested splitEndDate is in-between existing splitEndDate and existing endDate
requested endDate is in-between existing splitEndDate and existing endDate
existing splitEndDate is in-between requested splitEndDate and requested endDate
existing endDate is in-between requested splitEndDate and requested endDate

Большое спасибо

1 Ответ

2 голосов
/ 22 апреля 2011

Я предполагаю, что если вы очистите выполняемые вами манипуляции с датами, вам понравится ваш запрос.

Переместите его в переменную mysql:

SET @REQUEST = (CONVERT_TZ('" . $requested_start_time->format("Y-m-d G:i:s") . "', \"$tzone\", \"UTC\");

, а затемВаш код выглядит так:

        IF(
            splitStartDate != "0000 00:00:00",
            IF(
                (@REQUEST >= startDate AND @REQUEST < splitStartDate)
                OR
                (@REQUEST >= splitEndDate) AND @REQUEST < endDate))
                , 1, 0
            ),
            IF(
                (@REQUEST < endDate AND @REQUEST >= startDate), 1, 0        
            )
        ) = 1

Что не является необоснованным.Использование «X = 1» для меня выглядит как предложение where, поэтому я предпочел бы видеть

select count(*)
from bookings
where
(
    splitStartDate is not null
        and (
             (@REQUEST >= startDate AND @REQUEST < splitStartDate)
             OR
             (@REQUEST >= splitEndDate) AND @REQUEST < endDate))
        )
)
OR
(
    splitStartDate is null
        and (
            @REQUEST < endDate AND @REQUEST >= startDate
        )
)

Удачи!

...