MySQL预留系统 - 测试多种条件

时间:2012-11-05 19:36:03

标签: mysql sql

我正在研究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没有任何关于那个插槽的约会,所以我需要能够安排它们。房间也是如此,房间A在早上7点预约时使用,但B和C房仍可免费预定。

如何确定所有这些变量的开放广告位?我知道我可以测试每个组合的WHERE条件,如果我需要测试特定的医生或特定的治疗室,这是有效的。但是,如果我只想查看所有医生和房间的所有插槽,我的查询不起作用并单独测试所有可能的组合似乎不对,这只是如何在LEFT JOIN子句中获得正确条件的问题

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

感谢您的帮助,我在此处的上一个问题让我得到了上述查询,现在我只需要一些改进。问你需要的任何问题,我会在这里回答他们!

2 个答案:

答案 0 :(得分:2)

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

请注意,您不能只有一个表用于预约空档。每位医生都会有不同的时间表,包括假期等.soctor_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 |
+---------------------+----------------------+

希望有所帮助。

答案 1 :(得分: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