skip to Main Content

I need help with an assignment for school. I’ve only been doing SQL for 2 months and can’t figure this out. My teacher gave me some hints about using self joins. The database has 3 more tables, but I don’t think they are needed here.

The assignment is to write a query that will help hotel staff find double bookings (same room, same date). I’ve made a test database that has a double booking to control the query.

drop database if exists hoteltest;
create database hoteltest;
use hoteltest;

create table Roomreservation(
    ResNr int not null,
    RoomNr int not null,
    FromDate date not null,
        ToDate date not null,
    primary key (ResNr, RoomNr, FromDate)
    );
    
    
insert into Roomreservation
values
     (51, 102, '2008-12-05', '2008-12-07'),
     (51, 103, '2008-12-05', '2008-12-07'),
     (51, 104, '2008-12-05', '2008-12-09'),
     (52, 201, '2008-12-05', '2008-12-14'),
     (53, 102, '2008-12-04', '2008-12-10');
     
select * from Roomreservation;

Does anyone have a good and easy solution for this?

Honestly, I’m kinda stuck, I’ve been trying different solutions with concat_ws and the dates but with no results.

3

Answers


  1. You need to check for the range of Fromdate and todate. For this, you can use between. You also exclude the same row from the join. And you only extract one from the join since AxB will lead to BxA on the join. Therefore :

    SELECT t1.* FROM Roomreservation t1
    JOIN Roomreservation t2 ON t1.ResNr<>t2.ResNr AND t1.RoomNr=t2.RoomNr AND (t1.FromDate BETWEEN t2.FromDate AND t2.ToDate OR t2.FromDate BETWEEN t1.FromDate AND t1.ToDate);
    

    You should use an auto-incremented primary key, such as something as the resnumber but unique.

    Login or Signup to reply.
  2. The idea is to join the table on itself, looking for 2 records where the ResNo is different, the RoomNr is the same, and either the FromDate or the ToDate is between the other record’s FromDateToDate.

    I could write the query for you, but i believe in self-learning, especially for school assignments (rather than actual work).

    NOTE: don’t get lazy when it comes to naming, e.g. ResNr -> ReservationNumber
    will save you more time in the future when reading queries

    Login or Signup to reply.
  3. There is a, or at least a, double booking on the following dates:

    RoomNr d count(*)
    102 2008-12-04 2
    102 2008-12-05 2
    102 2008-12-06 2
    102 2008-12-07 2
    102 2008-12-08 2
    102 2008-12-09 2
    102 2008-12-10 2
    102 2008-12-11 2
    102 2008-12-12 2
    102 2008-12-13 2
    102 2008-12-14 2
    WITH recursive dates as (
        select min(FromDate)  as d FROM Roomreservation
        union all
        select adddate(d, INTERVAL 1 day) 
        from dates 
        where d<(select max(ToDate) from Roomreservation)
    )
    SELECT 
       RoomNr,
       d,
       count(*)
    FROM Roomreservation
    CROSS JOIN dates
    GROUP BY 
      RoomNr,
      d
    HAVING count(*) >1
    ORDER BY d, RoomNr
    
    • The WITH recursive.... is creating a table (dates) with all dates from the lower value of FromDate to the highest value of ToDate.
    • And then it’s just a matter of counting how many reservation there are on that day, for that RoomNr.

    see: DBFIDDLE

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search