I have the below table INDISPONIBILITY, that respresents the availability of teachers, for example the teacher a1 is not available from 25-Jan-21 to 25-Jan-21 from 8:00 to 12:00.
I want to select teachers available in a givin date and hour. For example with a date 26-Jan-21 and hour 10:00 the teachers a1 and a2 are not available, but at 12:00 are available.
id endDate startDate startHour endHoure fk_teacher 1 25-Jan-21 25-Jan-21 800 1200 a1 2 25-Jan-21 25-Jan-21 1400 1600 a1 3 26-Jan-21 26-Jan-21 1000 1130 a1 4 29-Jan-21 28-Jan-21 1200 1400 a2 5 26-Jan-21 26-Jan-21 1000 1130 a2
I tried with this query, but in this date 26-Jan-21 and hour 10:00 it returns the teachers a1 and a2.
public static String query = "SELECT * FROM ESP_ENSEIGNANT s n" +
" LEFT JOIN INDISPONIBILITY ds ON ds.fk_teacher = s.teacherIdn" +
" WHERE (?1 NOT BETWEEN ds.STARTDATE AND ds.ENDDATE) AND (?2 NOT BETWEEN ds.startHour AND ds.endHour)";
@Query(nativeQuery = true, value = query)
List<TeacherEntity> findAllByUps(Date effectDate, int hour);
Advertisement
Answer
It took me a moment to understand why dates and hours are separated in the table. But yes, the teacher a2 is not booked from 2021-01-28 12:00 until 2021-01-29 14:00, but each day from 2021-01-28 to 2021-01-29 at the hours 12:00 to 14:00. This makes sense.
We can also observe that enddate is inclusive (the teacher is booked on 2021-01-29) and the hour is exclusive (the teacher is booked until before 14:00). Another thing to notice is that we are not only talking about full hours here, as there is 11:30 in your sample data.
You want to see if a teacher is available at a certain hour, say 2021-01-26 10:00. You don’t say for how long, so I expect a full hour (i.e. until right before 11:00). This means, we check the date and see whether the hour falls into their time range. We check the time tables with NOT EXISTS or NOT IN. As fot the time range we need to check for overlapping ranges. 10:00-11:00 is in the range of 09:00-12:00, but also overlapping with 09:00-10:30 and 10:30-12:30
select * from teacher where teacher_id not in ( select fk_teacher from timetable where :date between startdate and enddate and starthour <= :hour + interval '1' hour and endhour > :hour );