我正在研究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子句中获得正确条件的问题
如果我不清楚,请告诉我,但我认为这是足够的信息。如果没有,我会添加你要求的任何内容!
感谢您的帮助,我在此处的上一个问题让我得到了上述查询,现在我只需要一些改进。问你需要的任何问题,我会在这里回答他们!
答案 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