开发者

comparing multiple dates within mySQL

开发者 https://www.devze.com 2023-02-26 22:03 出处:网络
We are working on a booking system that needs to support split appointments.These appointments have a first half, a break during which something else can be booked and then the second half.

We are working on a booking system that needs to support split appointments. These appointments have a first half, a break during which something else can be booked and then the second half.

The system also supports normal bookings which have a standard start and end.

We need to check the database to see if there are any existing bookings that overlap with a booking we wish to make.

We have done this in PHP before but need to do it solely in mysql in this situation.

the bookings table has:

startDate (always) splitStartDate (sometimes) splitEndDate (sometimes) endDate (always)

When the splitStartDate and splitEndDate are not being used for a booking they have a value of 0000-00-00 00:00:00

We started trying to build the mysql statement out of ifs, but it seems ridiculously long.

    "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 
        (

We know there has to be a much simpler way to do this but have been stumped as to what it is. We'd love any suggestions on how to build a mysql query for this.

When checking the availability we have been running the following checks (Sorry for how long this is, but that's the problem):

------------
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 开发者_如何学JAVAsplitstartDate
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

Thanks so much


My guess is that if you cleanup the date manipulation stuff you're doing, you'll like your query.

Move it to a mysql variable:

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

and then your code looks like this:

        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

Which is not unreasonable. Using "X = 1" looks like a where clause to me, so I'd prefer to see

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
        )
)

Good luck!

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号