Reputation: 11
Hi!
I have two tables, "room" and "busy". My busy table contains reservation records containing an arrival date and a departure date.
I wish to make a room selection that is not booked for two dates given.
Someone gives me the date to which he wants to reserve his room and to which he intends to leave, from that I want to be able to show the rooms that are available to him.
Busy Table => |IdRoom||ArrivalDate|DepartureDate|
Room Table => |IdRoom|NumRoom|And so on..|
I tried different queries but I don't get anything.
My tested query:
SELECT Room.*, Busy.*
FROM Room
INNER JOIN Busy ON Room.RoomdId= Busy.RoomdId
WHERE (@dateArr NOT BETWEEN 'Busy.ArrivalDate' AND 'Busy.DepartureDate')
AND (@dateDep NOT BETWEEN 'Busy.ArrivalDate' AND 'Busy.DepartureDate')
Thanks for your help in advance!
Upvotes: 0
Views: 148
Reputation: 1460
There are 4 scenarios where the date comparisons should say the room is busy. @Simonare was on the right track by using a sub-selection for the busy rooms, and then excluding them from the main SELECT * FROM Room
My kludgy little table illustrates the 4 failure scenarios:
12345678 -> Eight Dates in a row.
..BBBB.. -> Assume: These four Dates are 'B' busy. 'D' dates below are desired/requested.
.D...... -> Success: Desired is before busy dates
......D. -> Success: Desired is after busy dates
..DD.... -> Fails: Desired within busy dates
.DD..... -> Fails: Desired overlaps starting before beginning of busy dates
.....DD. -> Fails: Desired overlaps extending after ending of busy dates
.DDDDDD. -> Fails: Desired extends both before and after busy dates
These are the WHERE
clauses to remove the failures:
Request within busy dates: The Busy arrival date AT or AFTER desired arrival date AND Busy departure date LE desired departure date
SELECT 'Busy.DateArr' <= @dateArr AND 'Busy.DateDep' >= @dateDep
Request starts before Busy beginning: The desired arrival date is BEFORE the Busy arrival date AND the desired departure date is AFTER the Busy arrival date)
SELECT @dateArr < 'Busy.DateArr' AND @dateDep > 'Busy.DateArr'
Request ends After Busy ending: The desired arrival date is BEFORE Busy departure date AND the desired departure date is AFTER the Busy departure date
SELECT @dateArr < 'Busy.DateDep' AND @dateDep > 'Busy.DateDep'
Request extending beyond both begin & end: The desired arrival date is BEFORE Busy arrival date AND desired departure date is AFTER Busy departure date
SELECT @dateArr < 'Busy.DateArr' AND @dateDep > 'Busy.DateDep'
So the entire SQL becomes...
SELECT * FROM Room
WHERE NOT EXISTS (
SELECT 1 FROM Busy WHERE Room.RoomdId= Busy.RoomdId AND
((@dateArr>= 'Busy.DateArr' AND @dateDep<= 'Busy.DateDep') OR
(@dateArr < 'Busy.DateArr' AND @dateDep > 'Busy.DateArr') OR
(@dateArr < 'Busy.DateDep' AND @dateDep > 'Busy.DateDep') OR
(@dateArr < 'Busy.DateArr' AND @dateDep > 'Busy.DateDep') )
)
Apologies, I haven't actually run this, so with the complexity, there may be a logic or syntax error. You can test and debug each SELECT portion individually to ensure they are correct. Also, the judicious use of a little Boolean Algebra could significantly simplify the statement.
And ... I am assuming someone can arrive on a departure date.
Upvotes: 0
Reputation: 11
Ok so i've corrected my query.
That's the query i use:
SELECT *
FROM Room
WHERE RoomId in (
SELECT RoomID FROM Reservation WHERE EndDate <= @startDate OR
StartDate >= @endDate
)
There is surely a better way to do it but it does the job. Thank you all for helping me ;)
Upvotes: 1
Reputation: 1269513
First, you have a problem with the quotes. But I think that is probably just putting the values in the question.
Second, you don't want the columns from busy
. There is no match so they are not of interest.
Then the overlap logic is not correct. Something like:
SELECT r.*
FROM Room r LEFT JOIN
Busy b
ON r.RoomdId = b.RoomId AND
@dateArr <= b.DepartureDate AND
@dateDep >= b.ArrivalDate
WHERE b.RoomId IS NULL;
Your question is unclear whether someone can arrive on a departure date (and vice versa). If so, the <=
and >=
might need to lose the equality comparisons.
EDIT:
In MS Access, you can use NOT EXISTS
:
SELECT r.*
FROM Room r LEFT JOIN
WHERE NOT EXISTS (SELECT 1
FROM Busy b
WHERE r.RoomdId = b.RoomId AND
@dateArr <= b.DepartureDate AND
@dateDep >= b.ArrivalDate
);
Upvotes: 0
Reputation: 154
It would be helpful to see a few more columns of your tables. And you may want to consider refactoring them - They don't appear to be in 3rd normal form. Also its not clear if the BUSY table contains the entire history of all the times the rooms were rented. This should work if BUSY contains only current reservations:
SELECT IdRoom FROM BUSY WHERE @ArrivalDate >= DepartureDate AND @DepartureDate <= ArrivalDate
Upvotes: 0
Reputation: 30545
the query you are trying to use is logically wrong. Inner join has no use here. Please check the query below
SELECT Room.*
FROM Room
WHERE NOT EXISTS
(
SELECT 1 FROM Busy WHERE Room.RoomdId= Busy.RoomdId AND
(@dateArr BETWEEN 'Busy.ArrivalDate' AND 'Busy.DepartureDate') AND
(@dateDep BETWEEN 'Busy.ArrivalDate' AND 'Busy.DepartureDate')
)
Upvotes: 0