简体   繁体   中英

MYSQL query for find rows not overlapping other table

I have been stuck on this query for far too long. I always get close but not exact. It seems simple. Need to find rows in a table showing all available time slots that do not overlap any row from a table with appts scheduled. We need the computer to auto-fill a schedule with no overlap.

mysql> select * from existingApptsToNotOverlap order by startTime;
+---------------------+---------------------+
| startTime           | endTime             |
+---------------------+---------------------+
| 2015-05-28T10:30:00 | 2015-05-28T12:15:00 |
| 2015-05-29T10:15:00 | 2015-05-29T10:45:00 |
| 2015-05-29T11:00:00 | 2015-05-29T11:45:00 |
| 2015-05-29T12:00:00 | 2015-05-29T12:45:00 |
+---------------------+---------------------+
4 rows in set (0.00 sec)

mysql> select * from allAvailableSlots;
+---------------------+---------------------+
| startTime           | endTime             |
+---------------------+---------------------+
| 2015-05-28T09:00:00 | 2015-05-28T09:45:00 |
| 2015-05-28T09:15:00 | 2015-05-28T10:00:00 |
| 2015-05-28T09:30:00 | 2015-05-28T10:15:00 |
| 2015-05-28T09:45:00 | 2015-05-28T10:30:00 |
| 2015-05-28T10:00:00 | 2015-05-28T10:45:00 |
| 2015-05-28T10:15:00 | 2015-05-28T11:00:00 |
| 2015-05-28T10:30:00 | 2015-05-28T11:15:00 |
| 2015-05-28T10:45:00 | 2015-05-28T11:30:00 |
| 2015-05-28T11:00:00 | 2015-05-28T11:45:00 |
| 2015-05-29T09:00:00 | 2015-05-29T09:45:00 |
| 2015-05-29T09:15:00 | 2015-05-29T10:00:00 |
| 2015-05-29T09:30:00 | 2015-05-29T10:15:00 |
| 2015-05-29T09:45:00 | 2015-05-29T10:30:00 |
| 2015-05-29T10:00:00 | 2015-05-29T10:45:00 |
| 2015-05-29T10:15:00 | 2015-05-29T11:00:00 |
| 2015-05-29T10:30:00 | 2015-05-29T11:15:00 |
| 2015-05-29T10:45:00 | 2015-05-29T11:30:00 |
| 2015-05-29T11:00:00 | 2015-05-29T11:45:00 |
| 2015-05-30T09:00:00 | 2015-05-30T09:45:00 |
| 2015-05-30T09:15:00 | 2015-05-30T10:00:00 |
| 2015-05-30T09:30:00 | 2015-05-30T10:15:00 |
| 2015-05-30T09:45:00 | 2015-05-30T10:30:00 |
| 2015-05-30T10:00:00 | 2015-05-30T10:45:00 |
| 2015-05-30T10:15:00 | 2015-05-30T11:00:00 |
| 2015-05-30T10:30:00 | 2015-05-30T11:15:00 |
| 2015-05-30T10:45:00 | 2015-05-30T11:30:00 |
| 2015-05-30T11:00:00 | 2015-05-30T11:45:00 |
+---------------------+---------------------+
27 rows in set (0.00 sec)

Here is my latest attempt (after many other attempts):

mysql> select * from (select *, IF((slotStart<apptStart and slotEnd<apptStart) or (slotStart>apptEnd and slotEnd>apptEnd),1,0) as exclude from (select allSlots.startTime as slotStart, allSlots.endTime as slotEnd, existingAppts.startTime as apptStart, existingAppts.endTime as apptEnd from allSlots left join existingAppts on date(allSlots.startTime)=date(existingAppts.startTime) order by allSlots.startTime) as A group by slotStart, exclude desc) as B where exclude=0 group by slotStart;
+---------------------+---------------------+---------------------+---------------------+---------+
| slotStart           | slotEnd             | apptStart           | apptEnd             | exclude |
+---------------------+---------------------+---------------------+---------------------+---------+
| 2015-05-28T09:45:00 | 2015-05-28T10:30:00 | 2015-05-28T10:30:00 | 2015-05-28T12:15:00 |       0 |
| 2015-05-28T10:00:00 | 2015-05-28T10:45:00 | 2015-05-28T10:30:00 | 2015-05-28T12:15:00 |       0 |
| 2015-05-28T10:15:00 | 2015-05-28T11:00:00 | 2015-05-28T10:30:00 | 2015-05-28T12:15:00 |       0 |
| 2015-05-28T10:30:00 | 2015-05-28T11:15:00 | 2015-05-28T10:30:00 | 2015-05-28T12:15:00 |       0 |
| 2015-05-28T10:45:00 | 2015-05-28T11:30:00 | 2015-05-28T10:30:00 | 2015-05-28T12:15:00 |       0 |
| 2015-05-28T11:00:00 | 2015-05-28T11:45:00 | 2015-05-28T10:30:00 | 2015-05-28T12:15:00 |       0 |
| 2015-05-29T09:30:00 | 2015-05-29T10:15:00 | 2015-05-29T10:15:00 | 2015-05-29T10:45:00 |       0 |
| 2015-05-29T09:45:00 | 2015-05-29T10:30:00 | 2015-05-29T10:15:00 | 2015-05-29T10:45:00 |       0 |
| 2015-05-29T10:00:00 | 2015-05-29T10:45:00 | 2015-05-29T10:15:00 | 2015-05-29T10:45:00 |       0 |
| 2015-05-29T10:15:00 | 2015-05-29T11:00:00 | 2015-05-29T10:15:00 | 2015-05-29T10:45:00 |       0 |
| 2015-05-29T10:30:00 | 2015-05-29T11:15:00 | 2015-05-29T11:00:00 | 2015-05-29T11:45:00 |       0 |
| 2015-05-29T10:45:00 | 2015-05-29T11:30:00 | 2015-05-29T11:00:00 | 2015-05-29T11:45:00 |       0 |
| 2015-05-29T11:00:00 | 2015-05-29T11:45:00 | 2015-05-29T11:00:00 | 2015-05-29T11:45:00 |       0 |
| 2015-05-30T09:00:00 | 2015-05-30T09:45:00 | NULL                | NULL                |       0 |
| 2015-05-30T09:15:00 | 2015-05-30T10:00:00 | NULL                | NULL                |       0 |
| 2015-05-30T09:30:00 | 2015-05-30T10:15:00 | NULL                | NULL                |       0 |
| 2015-05-30T09:45:00 | 2015-05-30T10:30:00 | NULL                | NULL                |       0 |
| 2015-05-30T10:00:00 | 2015-05-30T10:45:00 | NULL                | NULL                |       0 |
| 2015-05-30T10:15:00 | 2015-05-30T11:00:00 | NULL                | NULL                |       0 |
| 2015-05-30T10:30:00 | 2015-05-30T11:15:00 | NULL                | NULL                |       0 |
| 2015-05-30T10:45:00 | 2015-05-30T11:30:00 | NULL                | NULL                |       0 |
| 2015-05-30T11:00:00 | 2015-05-30T11:45:00 | NULL                | NULL                |       0 |
+---------------------+---------------------+---------------------+---------------------+---------+
22 rows in set (0.00 sec)

You can see several timeslots on 5/29 are included that should not be as they conflict with an existing event on that date.

Is this even possible with queries or does it require application logic on the result sets?

I think I have it. This appears to work. Please correct me if I'm wrong.

select t1.startTime,t1.endTime,t2.endTime as appt from allSlots t1 left join existingAppts t2 on ((t1.startTime >= t2.startTime and t1.startTime < t2.endTime) or (t1.endTime > t2.startTime and t1.endTime <= t2.endTime)) where t2.endTime IS NULL order by t1.startTime;

+---------------------+---------------------+------+
| startTime           | endTime             | appt |
+---------------------+---------------------+------+
| 2015-05-28T09:00:00 | 2015-05-28T09:45:00 | NULL |
| 2015-05-28T09:15:00 | 2015-05-28T10:00:00 | NULL |
| 2015-05-28T09:30:00 | 2015-05-28T10:15:00 | NULL |
| 2015-05-28T09:45:00 | 2015-05-28T10:30:00 | NULL |
| 2015-05-29T09:00:00 | 2015-05-29T09:45:00 | NULL |
| 2015-05-29T09:15:00 | 2015-05-29T10:00:00 | NULL |
| 2015-05-29T09:30:00 | 2015-05-29T10:15:00 | NULL |
| 2015-05-30T09:00:00 | 2015-05-30T09:45:00 | NULL |
| 2015-05-30T09:15:00 | 2015-05-30T10:00:00 | NULL |
| 2015-05-30T09:30:00 | 2015-05-30T10:15:00 | NULL |
| 2015-05-30T09:45:00 | 2015-05-30T10:30:00 | NULL |
| 2015-05-30T10:00:00 | 2015-05-30T10:45:00 | NULL |
| 2015-05-30T10:15:00 | 2015-05-30T11:00:00 | NULL |
| 2015-05-30T10:30:00 | 2015-05-30T11:15:00 | NULL |
| 2015-05-30T10:45:00 | 2015-05-30T11:30:00 | NULL |
| 2015-05-30T11:00:00 | 2015-05-30T11:45:00 | NULL |
+---------------------+---------------------+------+
16 rows in set (0.00 sec)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM