MySQL 判断时间区间是否有交叉时间

在开发中,经常会遇到需要判断时间区间是否有交叉时间的需求。例如,在一个会议室预定系统中,需要判断一个会议室是否在某个时间段内被预定。本文将介绍如何使用 MySQL 数据库进行时间区间的交叉判断,并提供相应的代码示例。

问题描述

假设有以下的会议室预定表(meeting_room_booking):

id room_id start_time end_time
1 1 2021-01-01 09:00:00 2021-01-01 10:00:00
2 2 2021-01-01 11:00:00 2021-01-01 12:00:00
3 1 2021-01-01 13:00:00 2021-01-01 14:00:00

现在,我们需要判断给定的时间段是否与已有的会议室预定时间有交叉。

解决方案

MySQL 5.7 版本及以上提供了时间和日期的处理函数,可以方便地进行时间区间的比较和计算。我们可以使用以下的 SQL 查询语句来判断给定的时间段(start_time1, end_time1)是否与已有的时间段(start_time2, end_time2)有交叉:

SELECT COUNT(*) AS count
FROM meeting_room_booking
WHERE start_time1 <= end_time2 
AND end_time1 >= start_time2;

如果查询结果的 count 值大于 0,则表示给定的时间段与已有的时间段有交叉。

下面是一个具体的例子,假设我们需要判断会议室 1 是否在 2021-01-01 09:30:00 到 2021-01-01 10:30:00 这个时间段内被预定:

SET @start_time1 = '2021-01-01 09:30:00';
SET @end_time1 = '2021-01-01 10:30:00';

SELECT COUNT(*) AS count
FROM meeting_room_booking
WHERE @start_time1 <= end_time
AND @end_time1 >= start_time
AND room_id = 1;

如果查询结果的 count 值大于 0,则表示会议室 1 在该时间段内已被预定。

代码示例

下面是一个完整的代码示例,使用 PHP 和 PDO 扩展连接 MySQL 数据库,并判断会议室时间段是否有交叉:

<?php
$dbhost = 'localhost';
$dbname = 'test';
$dbuser = 'root';
$dbpass = 'password';

try {
    $dbh = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);

    $start_time = '2021-01-01 09:30:00';
    $end_time = '2021-01-01 10:30:00';
    $room_id = 1;

    $stmt = $dbh->prepare("SELECT COUNT(*) AS count
                           FROM meeting_room_booking
                           WHERE :start_time <= end_time
                           AND :end_time >= start_time
                           AND room_id = :room_id");
    $stmt->bindParam(':start_time', $start_time);
    $stmt->bindParam(':end_time', $end_time);
    $stmt->bindParam(':room_id', $room_id);
    $stmt->execute();

    $count = $stmt->fetchColumn();

    if ($count > 0) {
        echo "该时间段内会议室已被预定";
    } else {
        echo "该时间段内会议室未被预定";
    }

    $dbh = null;
} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
    die();
}
?>

请注意,以上代码仅是示例,并未考虑异常处理和安全性等因素,实际应用中需要根据具体情况进行优化和改进。

关系图

下面是会议室预定表的关系图:

erDiagram
    meeting_room_booking {
        id int PK
        room_id int
        start_time datetime
        end_time datetime
    }

序列图

下面是判断会议室时间段是否有交叉的序列图:

sequenceDiagram
    participant Client
    participant Server