I know title is really ridiculous. I couldn’t find how I can describe this.
This is my table structure

This is a car rental webpage. What I’m doing is I’m trying to figure out if a car is reserved in particular “pickup_date“ and “dropoff_date”.
I can get reserved cars with this query
SELECT
cars.model,
reservations.pickup_date,
reservations.dropoff_date,
reservations.car_id
FROM
cars
INNER JOIN reservations ON cars.car_id = reservations.car_id
WHERE
reservations.pickup_date <= '2012-04-08 10:50:26' OR
reservations.dropoff_date >= '2012-04-20 10:50:26'
However, there are some cars that are not reserved and they are not shown in this query, since I don’t have all car models in reservation. I have them in cars table.
The bottom line, I should eliminate the ones that I get from this query from the table that has all car models. Therefore, I will have cars which are not reserved + the ones that will be available after reserve dates.
It will get the results that I got from the query, and eliminate this results from cars table. After that It will show me.
I can do it with PHP. However, I want to learn if it is possible to do it with one query with mysql.
This is the solution that I came up with with the help of @cbuckley
SELECT
cars.*
FROM cars
LEFT JOIN (
SELECT
cars.car_id
FROM
cars
INNER JOIN reservations
ON cars.car_id = reservations.car_id
WHERE
(reservations.pickup_date <= '2012-04-08 10:50:26' AND reservations.dropoff_date >= '2012-04-20 10:50:26') OR
(reservations.pickup_date >= '2012-04-08 10:50:26' AND reservations.pickup_date <= '2012-04-20 10:50:26') OR
(reservations.dropoff_date <= '2012-04-20 10:50:26' AND reservations.dropoff_date >= '2012-04-08 10:50:26')
) AS reserved_cars
ON reserved_cars.car_id = cars.car_id
WHERE reserved_cars.car_id IS NULL;
You need to be careful distinguishing cars with no reservation at a given time and cars with a reservation at a time other than the given time. The former is what you’re after and could be achieved with a
WHERE NOT INclause. However as your cars and reservations system grows, this could become hideously slow. I would suggest the following:The inner query is the one you specified to find all reserved cars. You then join that back to the
carstable to find all cars which are not returned by the inner query. This works because you perform aLEFT JOINto the subquery and only return rows which didn’t have a match in the subquery.EDIT: If you want the query to find all cars which are available for a given period, your inner query needs to search for reservations which start or end within that period. You would therefore use the following condition: