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)
)

ユーザーが2つの日付を入力すると、Room and Reservationテーブルにクエリを実行して、現在利用可能なすべての部屋を返すSql Serverのクエリを作成することを念頭に置いていました(利用可能:/を持つ予約エントリがないことを意味します)またはユーザーが入力した日付の間にある。

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 Web サイトでこれをテストする必要があります。私のページには、ユーザーがチェックインとチェックアウトの 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>

101~109号室の9部屋と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. したがって、「checkindate」が「2012-09-01」で「checkoutdate」が「2012-09-05」のウェブサイトで検索すると、room101 行が返されますが、その部屋にはこれらの日付の予約エントリがないため、これを実行する必要がありますが、他の 8 つの部屋はすべて返されません。

  2. チェックイン日が '2012-01-01' でチェックアウト日が '2012-01-30' の検索を行う場合 < room101 の予約が既にあります。つまり、101 を除くすべての部屋の行が返されます。ただし、何も返されません。

誰かがこれで私を助けてくれませんか、私がどこで間違っているのか分かりますか?

アップデート:

この新しいクエリは私が探しているものですが、小さな問題があります

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
    );

これにより、room102-109 の間の結果が表示されますが、これは正しいですが、2012-01-30 を 2012-01-32 に変更すると、room101 が結果に追加されます。解決策はありますか?

4

2 に答える 2

2

日付の基準が間違っています。範囲の重複をテストするには、使用する必要があります

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

範囲 1 の開始が範囲 2 の終了より前であり、範囲 1 の終了が範囲 2 の開始の後にある場合は、重複があることを示しています。

右側のテーブルに置かれた条件は結合自体で指定する必要があるため、左の結合は機能しません。

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;

それ以外の場合は、実行順序に従って内部結合として扱われます。結合が評価され、右側のテーブルの null レコードのみが含まれ、where 句のレコードが削除されます。

編集: 最終フィルターがありません。クエリはすべての部屋を一覧表示し、それらの予約リストには予約が表示されます。予約なしで部屋を選択する必要がある場合は、追加してください

 WHERE Reservation.RoomNo is null

また、期間内にすべての部屋を予約したい場合は、左外部結合の代わりに内部結合を使用してください。

于 2012-09-03T21:45:21.283 に答える
0

あなたの問題は、左外部結合の代わりに結合を使用していることだと思います。ルーム101のReservationsテーブルにはアイテムが1つしかないため、ルームと予約に参加すると、ルーム101の1行のみが返されます(試してみてください..)代わりに、ルームテーブルのすべてのルームをルームに参加させます予約テーブルから、クエリは次のようになる必要があります。

Sql サーバー コード

 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' は dbo.Reservation.CheckInDate と dbo.Reservation.CheckOutDate の間にありません。

于 2012-09-03T16:42:35.130 に答える