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的界面;即,例如,客户可以将其指定为“1 个房间有 2 个成人”和“1 个房间有 2 个成人和 1 个房间有 3 个成人”。

到目前为止,这是我的 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

假设您已经解析了“自然语言”输入,将您的请求按 max_adults 分组,然后查询每个单独的类型;例如,对于“2 个房间 1 个成人和 3 个房间 2 个成人”发出两个单独的查询,分别为 (max_adults = 1,avail_rooms = 2) 和 (max_adults = 2,avail_rooms = 3)

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 回答
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上的演示

如果您想检索所有至少有一个选项的酒店

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 回答