5

これはホテルエージェントが様々なホテルから契約を取り、顧客が契約しているホテルを検索して予約できるようにする (そして利益を得る) プログラムのサンプルです。これが私のテーブルスキーマです。

CONTRACT (contract_id, hotel_id, valid_from, valid_to) 
ROOM (room_type, hotel_id, contract_id, price, max_adults_allowed, avail_rooms)
HOTEL (hotel_id, hotel_name, location)

検索の場合は、hotels.comのようなインターフェースです。例えば、「大人2名で1部屋」「大人2名で1部屋と大人3名で1部屋」のように指定できます。

これまでのSQLクエリは次のとおりです。

select h.name, h.location, r.type, r.price FROM HOTEL h, ROOM r, CONTRACT c 
WHERE c.contract_id = r.contract_id and c.hotel_id = h.hotel_id    --table joining
AND 'requested room lies within the contract valid period'  --check in and check out dates comparison
AND 'h.location is the user specified location' --requested location 
........

ルーム検索の詳細 (前述) をこのクエリに統合するのに問題があります。部屋の仕様を含めるためのSQLクエリの作成を手伝ってくれませんか。SQL Server を使用しています。前もって感謝します。

4

2 に答える 2

1

このスクリプトは、必要な部屋しかないホテルを取得します。ホテルに必要な部屋が 1 つしかない場合は除外されます。

更新 15.01.2013

IF OBJECT_ID('tempdb.dbo.#RoomParams') IS NOT NULL DROP TABLE dbo.#RoomParams
SELECT SUM(rooms) AS rooms, adults
INTO dbo.#RoomParams
FROM (VALUES(1, 2), -- 1 room with 2 adults
            (1, 2), -- 1 room with 2 adults
            (1, 3)) -- 1 room with 3 adults
p(rooms, adults)
GROUP BY adults

;WITH cte AS
 (
  SELECT h.hotel_id, h.hotel_name, h.location, r.room_type, r.price,
         SUM(avail_rooms) OVER (PARTITION BY h.hotel_id, r.max_adults_allowed) AS cnt,
         r.max_adults_allowed        
  FROM CONTRACT c JOIN ROOM r ON c.contract_id = r.contract_id AND c.hotel_id = r.hotel_id
                  JOIN HOTEL h ON c.hotel_id = h.hotel_id
  WHERE c.valid_from >= '20130114' AND c.valid_to <= '20130115'  --check in and check out dates comparison
        AND h.location IN ('loc4') --requested location        
  )
  SELECT *
  FROM cte s
  WHERE 
    NOT EXISTS (                  
                SELECT rp.adults
                FROM dbo.#RoomParams rp
                EXCEPT
                SELECT st.max_adults_allowed
                FROM cte st JOIN dbo.#RoomParams r ON st.cnt >= r.rooms AND st.max_adults_allowed = r.adults
                WHERE st.hotel_id = s.hotel_id                  
                ) AND s.max_adults_allowed IN (SELECT adults FROM dbo.#RoomParams)

SQLFiddle のデモ

少なくとも 1 つのオプションがあるすべてのホテルを取得する場合

IF OBJECT_ID('tempdb.dbo.#RoomParams') IS NOT NULL DROP TABLE dbo.#RoomParams
SELECT rooms, adults
INTO dbo.#RoomParams
FROM (VALUES(1, 2), -- 1 room with 2 adults
            (1, 2), -- 1 room with 2 adults
            (1, 3)) -- 1 room with 3 adults
p(rooms, adults)

;WITH cte AS
 (
  SELECT h.hotel_id, h.hotel_name, h.location, r.room_type, r.price,
         SUM(avail_rooms) OVER (PARTITION BY h.hotel_id, r.max_adults_allowed) AS cnt,
         r.max_adults_allowed
  FROM CONTRACT c JOIN ROOM r ON c.contract_id = r.contract_id AND c.hotel_id = r.hotel_id
                  JOIN HOTEL h ON c.hotel_id = h.hotel_id
  WHERE c.valid_from >= '20130114' AND c.valid_to <= '20130115'  --check in and check out dates comparison
        AND h.location IN ('loc4') --requested location
  )
  SELECT hotel_name, location, room_type, price, max_adults_allowed, cnt
  FROM cte c 
  WHERE EXISTS (
                SELECT 1
                FROM dbo.#RoomParams r 
                WHERE c.cnt >= r.rooms AND c.max_adults_allowed = r.adults
                )
于 2013-01-14T21:43:57.043 に答える
1

「自然言語」の入力を既に解析していると仮定して、リクエストを max_adults でグループ化し、それぞれの個別のタイプに対してクエリを実行します。たとえば、「大人 1 名で 2 部屋、大人 2 名で 3 部屋」の場合、(max_adults = 1, avail_rooms = 2) と (max_adults = 2, avail_rooms = 3) を使用して 2 つの個別のクエリを発行します。

select h.name, h.location, r.type, r.price, r.room_id FROM HOTEL h, ROOM r, CONTRACT c 
WHERE c.contract_id = r.contract_id and c.hotel_id = h.hotel_id
AND c.valid_from >= ? AND c.valid_to <= ? AND h.location = ?
AND r.max_adults = ? AND r.avail_rooms >= ?

これはmax_adults の完全一致のみを検索し、部屋を「アンダーブッキング」するオプションを提供しないことに注意してください。顧客が大きな部屋を予約できるようにする (そして、満室になることなくそれに応じて支払う) 場合は、次の戦略を使用できます。最初に元のクエリを試してから、(「人工ゲスト」を追加して) 大きな部屋を検索します。

たとえば、元のリクエストが「1 トリプル、1 ダブル、1 シングル」だった場合は、最初にそれを試してから、「1 トリプル 2 ダブル」、「2 トリプル 1 ダブル」、「3 トリプル」の順に試してください。「変更された」クエリごとに、上記の SQL を使用します。最初に成功したものが、顧客にとって最も安価なオプションになります。

これにはいくつかの SQL トランザクションが含まれますが、それぞれに単純な結合があり、おそらく複雑なステートメントよりも高速に動作します。

もっと制御できる場合は、スキーマを変更して、各部屋を個別に説明することになるでしょう。

ROOM (room_id, room_type, hotel_id, contract_id, price, max_adults_allowed)
BOOKING (room_id, checkin, checkout)
于 2013-01-14T07:40:57.370 に答える