如何在时间范围内检查预订是否存在?

时间:2016-03-31 12:03:52

标签: php mysql datetime pdo

我在会议室预订系统上工作,我无法确定是否在规定的时间范围内拍摄了房间,我使用当前日期格式并在表格中将类型设置为DATETIMEYYYY-MM-DD HH:II:SS

这是我目前的代码:

//Function to check if a booking exists:
function bookingExist($DateStart, $DateEnd, $RoomNo) {
    global $DB;

    $sql = "SELECT * FROM bookings WHERE date_start = :dateStart AND date_end = :dateEnd AND room_no = :roomNo";
    $Q = $DB->prepare($sql);
    $Q->bindParam(':dateStart', $DateStart);
    $Q->bindParam(':dateEnd', $DateEnd);
    $Q->bindParam(':roomNo', $RoomNo);
    $Q->execute();

    if ($Q->rowCount()) {
        //A record exists...
        return true;
    } else {
        //no record exists
        return false;
    }
}

有没有办法在sql查询中执行此操作?

示例:房间A在2016-03-31 15:00:00和2016-03-31 17:30:00之间预订,然后用户尝试为2016-03-31 16的房间A创建新预订: 30:00 - 2016-03-31 17:00:00,由于预订,应该返回1条记录

3 个答案:

答案 0 :(得分:5)

SELECT *
FROM bookings
WHERE
  (
    :dateStart BETWEEN date_start AND date_end
    OR :dateEnd BETWEEN date_start AND date_end
    OR date_start BETWEEN :dateStart AND :dateEnd
  )
  AND room_no = :roomNo

如果在给定时间内没有预订房间,这将为您提供零行:dateStart - :dateEnd。 :dateStart BETWEEN date_start AND date_end会检查它是否已在开始时间预订,:dateEnd BETWEEN date_start AND date_end会检查是否在结束时间预订了它,而最后一个date_start BETWEEN :dateStart AND :dateEnd也是重要的,它会检查是否有房间是介于两者之间(例如较短的时期)

编辑:或时而不是AND;)

EDIT2:要排除开始和结束时间,您必须展开BETWEEN关键字并使关系仅为<

SELECT *
FROM bookings
WHERE
  (
    (date_start < :dateStart AND :dateStart < date_end)
    OR (date_start < :dateEnd AND :dateEnd < date_end)
    OR (:dateStart < date_start AND date_start < :dateEnd)
  )
  AND room_no = :roomNo

答案 1 :(得分:0)

在sql查询中使用BETWEEN怎么样?您需要设置要检查的日期/时间参数(这将是给定示例中第二个用户请求的日期/时间)。

$firstDate = //start of time period you are checking;
$lastDate = //end of time period you are checking;
 $Q->bindParam(':firstDate ', $firstDate );
 $Q->bindParam(':lastDate ', $lastDate );

 $sql = "SELECT * FROM bookings WHERE :date_start BETWEEN :firstDate AND :lastDate  AND room_no = :roomNo";

答案 2 :(得分:0)

插入前检查

INSERT INTO .... SELECT .. WHERE NOT EXISTS (SELECT ...)

CASE

<块引用>

[booking1 10/7/21 11:00 - 11:30]
[---new--- 10/7/21 11:30 - 11:20]
[预订 2 10/7/21 12:00 - 12:30]

如果预订不存在,您可以使用以下语法插入预订:

-- new booking [b1][new][b2]
SET @s = '2021-07-10 11:30:00';
SET @e = '2021-07-10 12:00:00';

INSERT INTO Appointments
        (col1, col2, starts, ends) 
    SELECT 'some data', 'some data', @s, @e
    WHERE NOT EXISTS
        (SELECT id FROM Appointments -- search for collision points
        WHERE 
            ((starts <= @s AND @s < ends)
            OR (starts < @e AND @e <= ends)
            OR (@s <= starts AND starts < @e)
            ))
        AND (1=1) -- some other conditions
;

如果在 WHERE NOT EXISTS (SELECT...) 语句中没有返回数据,INSERT 将继续。如果 SELECT 至少返回一行,INSERT 将不会被执行。

以上示例允许预订开始和结束与新预订重叠。请注意,新预订从 11:30 开始。同时在 11:30 结束预订,这已经在我们的虚构数据库中。同样适用于新预订结束的时间 - 它也与预订 nr 2 的开始重叠,这是可以的。上述查询适用于这种情况。如果您改用 BETWEEN,这将不包括这种情况。

在大多数情况下,这会产生意想不到的结果:

WHERE NOT EXISTS 
(SELECT id FROM your_table
    WHERE 
        ((@s BETWEEN starts AND ends
            OR @e BETWEEN starts AND ends
            OR starts BETWEEN @s AND @e))
        AND (1=1)) -- replace (1=1) with other mandatory conditions
    LIMIT 1; 

这将产生正确的结果:

WHERE NOT EXISTS
(SELECT id FROM your_table
    WHERE 
        ((starts <= @s AND @s < ends)
            OR (starts < @e AND @e <= ends)
            OR (@s <= starts AND starts < @e))
        AND (1=1)) -- replace (1=1) with other mandatory conditions
    LIMIT 1; conditions