I’m working on a reservation system in MySQL and I’m having a bit of trouble with my query for finding the next available appointment slots.
My days are broken down into 15-minute slots (00:00:00 – 00:14:59, 00:15:00 – 00:29:59, etc.). Table structure so far:
appointments table:
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 Table:
CREATE TABLE IF NOT EXISTS `apptSlots` (
`startDT` datetime NOT NULL,
`endDT` datetime NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
The apptSlots table is already filled with all the 15 minute slots for 2012, as I explained above.
I have a query that can successfully show me the slots that aren’t taken in any way (no appointments scheduled at all).
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
What I need to do now is search for appointment slots across multiple physicians, multiple rooms, etc. For example, if Physician A makes an appointment for 7am – 8am, that time slot no longer shows up in my query above. But Physician B and C don’t have any appointments for that slot, so I need to be able to schedule them. The same goes for rooms, Room A is used by the 7am appointment, but room B and C are still free to be scheduled.
How can I determine open slots with all these variables? I know I can test with WHERE conditions for each combination and this works if I need to test for a specific doctor, or a specific room for a treatment. But, if I just want to see all slots across all doctors and rooms, my query doesn’t work and testing all possible combinations individually doesn’t seem right, it’s just a matter of how to get the right conditions into the LEFT JOIN clause.
Please let me know if I’m being unclear, but I think this is enough info. If not, I’ll add in whatever you ask for!
Thank you for your help, my previous question on here got me as far as my query above, now I just need some refinement. Ask any questions you need, I’ll be here to answer them!
As requested, here’s an answer put together from my various comments:
Note that you can’t have just one table for appointment slots. Each doctor will have a different schedule, including vacations, etc. The doctor_id should be part of an available_appointments table.
You also have “resources”, like the appointment room, or portable equipment, etc. These should be in a different table (available_resources?), with their own availability and scheduling.
As for finding blocks of time, try this:
EDIT:
Here was my test data:
So there’s a 30-minute block, then an hour block, then another 30-minute block.
The inner query does the heavy lifting and produces the following output. The last two columns are just to maintain the two variables, and should be ignored.
The outer query allows you to get just the ones with the appropriate block_size. You’re getting the start time of the 4th block.
MySQL doesn’t let you set multiple variables at once in a query (you have to do that in a procedure), which is disappointing when trying to mess around like this.
The easiest thing that comes to mind would be to take the 4th period and subtract back to the start of the first period, so the outer query would look like this:
Hope that helps.