2

架构

    CREATE TABLE "Rooms"(

    RoomNo int NOT NULL,
    RoomType nvarchar(20) NULL,
    PricePerNight money NULL,
    MaximumOccupancy int NULL,
    NoOfBeds int NULL,
    NoOfBathrooms int NULL,
    Entertainment bit NULL,
    RoomService bit NULL,
    Gym bit NULL,

    CONSTRAINT PK_Rooms PRIMARY KEY(RoomNo)
)

CREATE TABLE "Reservation"(

    ReservationID int IDENTITY (1,1) NOT NULL,
    CustomerID int NOT NULL,
    RoomNo int NOT NULL,
    CheckInDate date NOT NULL,
    CheckOutDate date NOT NULL,
    NoOfDays int NOT NULL,

    CONSTRAINT PK_Reservation PRIMARY KEY(ReservationID),

    CONSTRAINT FK_Reservation_Customers_CustID FOREIGN KEY(CustomerID)  
        REFERENCES dbo.Customers(CustomerID),

    CONSTRAINT FK_Reservation_Rooms_RoomNo FOREIGN KEY(RoomNo)
        REFERENCES dbo.Rooms(RoomNo)
)

我想为 Sql Server 创建一个查询,当用户输入 2 个日期时,它将查询 Room 和 Reservation 表以带回所有当前可用的房间(可用:意味着没有预订条目有/或在用户输入的日期之间。

Sql-Server-Code

 SELECT dbo.Rooms.RoomNo
 FROM dbo.Rooms JOIN dbo.Reservation
 ON (dbo.Rooms.RoomNo = dbo.Reservation.RoomNo)
 WHERE '2012-02-01' NOT BETWEEN dbo.Reservation.CheckInDate AND dbo.Reservation.CheckOutDate
 AND '2012-02-05' NOT BETWEEN dbo.Reservation.CheckInDate AND dbo.Reservation.CheckOutDate;

^ 我对此进行了测试,在我进行的测试中,它产生了我想要的结果。所以我现在需要在我的 ASP.Net 网站上进行测试。在我的页面上,我有一个搜索框,用户可以在其中输入 2 个日期、签入和签出。这将再次返回所有可用的房间,所以我想。

ASP.Net Code Search Box

<div id="searchContainer">
    <form id="searchForm">
    <ul id="searchBox">
        <li>Search</li>
        <hr />
        <li>Check In Date</li>
        <li class="CiMenu">
            <asp:TextBox ID="txtBoxCheckIn" runat="server" />
            <ajaxtoolkit:CalendarExtender ID="CalendarExtender2" runat="server" TargetControlID="txtBoxCheckIn"
                Format="yyyy-MM-dd" />
        </li>
        <li>Check Out Date</li>
        <li class="CoMenu">
            <asp:TextBox ID="txtBoxCheckOut" runat="server" />
            <ajaxtoolkit:CalendarExtender ID="CalendarExtender1" runat="server" TargetControlID="txtBoxCheckOut"
                Format="yyyy-MM-dd" />
        </li>
        <li>
            <asp:Button ID="searchButton" runat="server" Text="Search" 
                PostBackUrl="~/Rooms.aspx" />
        </li>
    </ul>
    </form>
</div>

ASP.Net Code For my query.

    <asp:SqlDataSource ID="RoomDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:HotelProjectConnectionString %>"
        SelectCommand="SELECT * FROM Rooms JOIN Reservation
        ON (Rooms.RoomNo = Reservation.RoomNo)
        WHERE (@CheckIn NOT BETWEEN Reservation.CheckInDate AND Reservation.CheckOutDate)
        AND ( @CheckOut NOT BETWEEN Reservation.CheckInDate AND Reservation.CheckOutDate)">
        <SelectParameters>
            <asp:ControlParameter ControlID="txtBoxCheckIn" Name="CheckIn" PropertyName="Text"
                Type="DateTime" />
            <asp:ControlParameter ControlID="txtBoxCheckOut" Name="CheckOut" PropertyName="text"
                Type="DateTime" />
        </SelectParameters>
    </asp:SqlDataSource>

我创建了 9 个不同的房间 101-109 和 1 个预订条目。

INSERT Reservation(CustomerID,RoomNo,CheckInDate,CheckOutDate,NoOfDays)
    VALUES(1,101,'2012-01-01','2012-01-30', DATEDIFF(day,'2012-01-01','2012-01-30'))
  1. So now if i do a search on my website where the "checkindate" is '2012-09-01' and "checkoutdate" is '2012-09-05'. It returns room101 row which it should do as theres no reservation entry with those dates for that room, however it doesn't return all the other 8 rooms.

  2. If i do a search where the checkindate is '2012-01-01' and checkoutdate is '2012-01-30' < there is already a reservation for this for room101. Meaning it should bring back all the room rows except 101. However it doesn't return anything.

Could someone please help me with this, can you see where i am going wrong.

UPDATE:

This new Query is what i'm looking for cept it has a minor problem

SELECT *
FROM dbo.Rooms
WHERE NOT EXISTS
  (select *
    from dbo.Reservation
    where dbo.rooms.RoomNo = dbo.Reservation.RoomNo
    AND '2012-01-01' BETWEEN dbo.Reservation.CheckInDate AND dbo.Reservation.CheckOutDate
    AND '2012-01-30' BETWEEN dbo.Reservation.CheckInDate AND dbo.Reservation.CheckOutDate
    );

This will show results between room102-109 which is correct however if we change the 2012-01-30 to 2012-01-32 it adds room101 to the result which it shouldn't. Any solution?

4

2 回答 2

2

Your date criteria is wrong. To test for overlapping ranges you should use

where '2012-01-01' <= dbo.Reservation.CheckOutDate
  and '2012-01-30' >= dbo.Reservation.CheckInDate

It says that if beginning of range1 is before end of range two, and end of range1 is after beginning of range2, there is overlap.

Left join is not working for you because conditions put on right side table must be specified in join itself:

SELECT dbo.Rooms.RoomNo
  FROM dbo.Rooms 
  LEFT JOIN dbo.Reservation
    ON dbo.Rooms.RoomNo = dbo.Reservation.RoomNo
   AND '2012-01-01' <= dbo.Reservation.CheckOutDate
   AND '2012-01-30' >= dbo.Reservation.CheckInDate;

Otherwise it is treated as inner join by following execution order - join is evaluated and includes null records from right side table only to eliminate those records in where clause.

EDIT: The final filter is missing. The query lists all rooms and for those reserved lists a reservation. If you need to select rooms without reservations add

 WHERE Reservation.RoomNo is null

And if you want all rooms reserved in a period use inner join instead of left outer join.

于 2012-09-03T21:45:21.283 回答
0

I think your problem is that you are using join instead of left outer join. There is only one item in th Reservations table with room 101 so if you do join on room and reservation it will only return 1 row with room 101 (try it..) instead you want all the rooms from the rooms table to join the rooms from reservations table, so your query needs to look like this:

Sql-Server-Code

 SELECT dbo.Rooms.RoomNo  FROM dbo.Rooms LEFT OUTER JOIN dbo.Reservation  ON (dbo.Rooms.RoomNo = dbo.Reservation.RoomNo)  WHERE '2012-02-01' NOT BETWEEN dbo.Reservation.CheckInDate AND dbo.Reservation.CheckOutDate  AND '2012-02-05' NOT BETWEEN dbo.Reservation.CheckInDate AND dbo.Reservation.CheckOutDate;

于 2012-09-03T16:42:35.130 回答