0

I have a booking system and I have to check if a date or a date range is not in between of date ranges saved in MySQL.

Here is my table:

bookings(id, property_id, booked_from_date, booked_to_date)

Each property can have none, one or multiple dates booked.

My query to check if a certain date or range is not in between one of the booked periods is

SELECT p.id, p.title
FROM properties p 
LEFT JOIN bookings b ON p.id = b.property_id 
WHERE 
    COALESCE('selected_from_date' NOT BETWEEN p.booked_from_date AND b.booked_to_date , TRUE) AND 
    COALESCE('selected_to_date' NOT BETWEEN p.booked_from_date AND b.booked_to_date , TRUE)
GROUP BY main.id

My logic is that if a certain date is not in between a booked range then it is available but the query does not return the correct results.

Is there any way of excluding all properties that are available between those dates ?

Thank you

EDIT

Here is the table which holds the booked ranges

id boat_id booking_id booked_from_date booked_to_date
 5      22 NULL       2016-05-28       2016-06-04
 6      22 NULL       2016-07-02       2016-07-09
 7      22 NULL       2016-07-16       2016-07-23
 9      25 NULL       2016-06-04       2016-06-11

Here is the parent table

 id title
 21 Vacanza tra comfort e benessere su barca a vela ad...
 22 Vacanza in Barca a Vela su Gib Sea 372
 23 Vacanza da sogno su un Motor Yacht
 24 Capri & Costiera Amalfitana
 25 Golfo di Napoli in barca a vela
 26 Il 44 piedi che sorprende

What i expect:

  • If I search for 2016-05-30 I expect to return all boats except id 22, because the date 2016-05-30 is between a range already booked.

  • If I search from 2016-06-05 to 2016-06-10 I expect to return all boats except id 25

Hope this helps

Strawberry
  • 33,750
  • 13
  • 40
  • 57
C. Ovidiu
  • 1,104
  • 2
  • 18
  • 38
  • 1
    You have period `selected_from_date - selected_to_date` and want to check if it intersects with any record in `bookings` table (where period is `booked_from_date - booked_to_date`)? And find rows in `properties` where selected period is not booked, right? – Andrew May 16 '16 at 15:16
  • If you like, consider following this simple two-step course of action: 1. If you have not already done so, provide proper CREATE and INSERT statements (and/or an sqlfiddle) so that we can more easily replicate the problem. 2. If you have not already done so, provide a desired result set that corresponds with the information provided in step 1. – Strawberry May 16 '16 at 15:21
  • @Andrew I want to find any results that are not booked on a selected date, or a selected date range. Similar to any booking system. – C. Ovidiu May 16 '16 at 15:30
  • @Strawberry I will update my question shortly – C. Ovidiu May 16 '16 at 15:31
  • What's the difference between `id` and `booking_id` ?!? – Strawberry May 16 '16 at 15:49
  • Search for date range intersection in a NOT EXISTS subquery. – Paul Spiegel May 16 '16 at 15:53
  • @Strawberry That is a field that in this context is irrelevant. – C. Ovidiu May 16 '16 at 15:55
  • @PaulSpiegel Hi, could you provide some examples or articles ? Thank you – C. Ovidiu May 16 '16 at 15:55
  • [mysql-range-date-overlap-check](http://stackoverflow.com/questions/2545947/mysql-range-date-overlap-check) – Paul Spiegel May 16 '16 at 15:57

1 Answers1

3

This query will find all not booked items from properties. Main idea is to search booked items (and place condition for it in JOIN bookings). Then transform JOIN into LEFT JOIN with WHERE bookings.id IS NULL - it will reverse condition from booked to not booked.

SELECT p.id, p.title
FROM properties p 
LEFT JOIN bookings b ON p.id = b.property_id
  AND b.booked_from_date <= 'selected_to_date'
  AND b.booked_to_date >= 'selected_from_date'
WHERE b.id IS NULL
Andrew
  • 1,858
  • 13
  • 15
  • @C.Ovidiu Note that 'selected_to_date' and 'selected_from_date' might be the same day, and note how 'to' is paired with `from` and 'from' is paired with `to`. – Strawberry May 16 '16 at 16:20
  • With some tweaking I managed to make this work. My original query has a lot of other search parameters as well, so I wanted to ask if the performance impact is noticeable ? Never the less, I thank you very much for the help. @Strawberry It had me confused a bit, I then realized they were inverted – C. Ovidiu May 16 '16 at 16:37
  • 1
    This will be not slower than any `BETWEEN` condition. You probably already has index on `bookings.property_id` (foreign key to some other table). And this query can use indexes on `booked_from_date` and `booked_to_date` (if you have really big data or just want to add it for optimization). So, all conditions can be resolved with index scan - this must be as fast as possible ;-) – Andrew May 16 '16 at 16:43