0

我正在使用 MySQL 中的预订系统,但在查找下一个可用的预约空档时遇到了一些麻烦。

我的日子被分成 15 分钟的时段(00:00:00 - 00:14:59、00:15:00 - 00:29:59 等)。到目前为止的表结构:

约会表:

CREATE TABLE IF NOT EXISTS `appointments` (
`appointmentID` int(9) unsigned NOT NULL AUTO_INCREMENT,
`patientID` int(9) unsigned NOT NULL,
`apptTitle` varchar(50) NOT NULL,
`apptDT` datetime NOT NULL,
`apptLength` int(4) NOT NULL,
`apptStatus` varchar(25) NOT NULL,
`physician` int(9) unsigned NOT NULL,
`apptType` varchar(30) NOT NULL,
`apptLocation` varchar(25) NOT NULL,
PRIMARY KEY (`appointmentID`),
KEY `patientID` (`patientID`),
KEY `physician` (`physician`),
KEY `apptStatus` (`apptStatus`),
KEY `apptLocation` (`apptLocation`),
KEY `apptType` (`apptType`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;

apptSlots 表:

CREATE TABLE IF NOT EXISTS `apptSlots` (
`startDT` datetime NOT NULL,
`endDT` datetime NOT NULL,
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

apptSlots 表已经填满了 2012 年的所有 15 分钟时段,正如我在上面解释的那样。

我有一个查询可以成功地向我显示未以任何方式占用的插槽(根本没有安排约会)。

SELECT a.*
FROM apptSlots AS a
LEFT JOIN appointments AS b
ON a.endDT
BETWEEN b.apptDT AND DATE_ADD(b.apptDT, INTERVAL b.apptLength MINUTE)
AND b.appointmentID IS NULL

我现在需要做的是跨多个医生、多个房间等搜索预约时段。例如,如果医生 A 预约早上 7 点 - 早上 8 点,则该时间段不再显示在我上面的查询中。但医师 B 和 C 没有任何预约该时段,所以我需要能够安排他们。房间也是如此,早上 7 点的预约使用房间 A,但房间 B 和 C 仍然可以自由安排。

如何确定所有这些变量的开放槽?我知道我可以针对每种组合使用 WHERE 条件进行测试,如果我需要针对特定​​的医生或特定的治疗室进行测试,这将有效。但是,如果我只想查看所有医生和房间的所有插槽,我的查询不起作用并且单独测试所有可能的组合似乎不正确,这只是如何将正确的条件放入 LEFT JOIN 子句的问题.

如果我不清楚,请告诉我,但我认为这是足够的信息。如果没有,我会添加任何你要求的东西!

感谢您的帮助,我之前的问题在这里得到了我上面的查询,现在我只需要一些改进。有什么问题可以问,我会来解答的!

4

2 回答 2

2

根据要求,这是从我的各种评论中汇总的答案:

请注意,您不能只有一张桌子用于预约空档。每个医生都有不同的日程安排,包括假期等。医生 ID 应该是 available_appointments 表的一部分。

您还拥有“资源”,例如约会室或便携式设备等。它们应该位于不同的表中(available_resources?),并具有自己的可用性和日程安排。

至于寻找时间块,试试这个:

set @last_time = null;
set @block_size = 1;

select *
from (
  select startDT,
    case when @last_time is null or startDT = date_add(@last_time, interval 15 minute)
      then @block_size := @block_size + 1
      else @block_size := 1
    end as block_size,
    @last_time := startDT
  from foo_appt
) foo
where block_size = 4;

编辑:

这是我的测试数据:

+---------------------+
| startDT             |
+---------------------+
| 2012-11-06 13:00:00 |
| 2012-11-06 13:15:00 |
| 2012-11-06 14:00:00 |
| 2012-11-06 14:15:00 |
| 2012-11-06 14:30:00 |
| 2012-11-06 14:45:00 |
| 2012-11-06 16:00:00 |
| 2012-11-06 16:15:00 |
+---------------------+

所以有一个 30 分钟的时间段,然后是一个小时的时间段,然后是另一个 30 分钟的时间段。

内部查询完成繁重的工作并产生以下输出。最后两列只是维护两个变量,应该忽略。

+---------------------+------------+-------------+-----------------------+
| startDT             | block_size | @block_size | @last_time := startDT |
+---------------------+------------+-------------+-----------------------+
| 2012-11-06 13:00:00 |          1 |           1 | 2012-11-06 13:00:00   |
| 2012-11-06 13:15:00 |          2 |           2 | 2012-11-06 13:15:00   |
| 2012-11-06 14:00:00 |          1 |           1 | 2012-11-06 14:00:00   |
| 2012-11-06 14:15:00 |          2 |           2 | 2012-11-06 14:15:00   |
| 2012-11-06 14:30:00 |          3 |           3 | 2012-11-06 14:30:00   |
| 2012-11-06 14:45:00 |          4 |           4 | 2012-11-06 14:45:00   |
| 2012-11-06 16:00:00 |          1 |           1 | 2012-11-06 16:00:00   |
| 2012-11-06 16:15:00 |          2 |           2 | 2012-11-06 16:15:00   |
+---------------------+------------+-------------+-----------------------+

外部查询允许您只获取具有适当 block_size 的查询。您将获得第 4 个区块的开始时间

MySQL 不允许你在一个查询中一次设置多个变量(你必须在一个过程中这样做),这在试图像这样乱七八糟时令人失望。

想到的最简单的事情是取第 4 个周期并减去第一个周期的开头,因此外部查询如下所示:

select date_sub(startDT, interval 15 * (block_size-1) minute) as appointment_time,
    block_size*15 as appointment_duration
from ( ...

+---------------------+----------------------+
| appointment_time    | appointment_duration |
+---------------------+----------------------+
| 2012-11-06 14:00:00 |                   60 |
+---------------------+----------------------+

希望有帮助。

于 2012-11-06T17:36:18.717 回答
0

尝试这个。我相信这应该可以解决问题,假设您有一张医生桌。

SELECT  a.* 

FROM    apptSlots AS a 

        CROSS JOIN employees p 

        LEFT JOIN appointments AS b 
        ON p.employeeID = b.physician 
        AND a.endDT BETWEEN b.apptDT AND DATE_ADD(b.apptDT, INTERVAL b.apptLength MINUTE)

WHERE   b.appointmentID IS NULL
于 2012-11-05T20:18:29.027 回答