【问题标题】:query for available rooms in hotel reservation在酒店预订中查询可用房间
【发布时间】:2011-08-18 10:12:18
【问题描述】:

我的任务是创建一个在线酒店预订系统。我遇到的问题是查找特定日期范围内特定房间类别的可用房间的查询。我的数据库设计涉及 4 个表。数据库设计如下:

tbl_reservationdetails ( stores the general details of the reservation )
 pk resrvdtl_id (primary key)
 fk client_id (insignificant for now)
    start_date (customer's check-in-date)
    end_date (customer's check-out-date)

tbl_reservation (stores the rooms reserved for a particular reservation )
 pk reserv_id (primary key)
 fk resrvdtl_id (foreign key, to know to whom and when the room should be occupied)
 fk room_id (the room reserved)

tbl_room
 pk room_id (primary key)
    room_number 
 fk room_categId (to know what category this room belongs to)

tbl_roomcategory
 pk room_categId (primary key)
    room_category (description of category.. example: Suite, Superior, Deluxe etc. in my case... there are four categories)

用户输入的是日期(开始和结束),以及他想要的房间类别。我对此很陌生......我如何查询以检查特定日期该类别的可用房间??????

对此的任何回应将不胜感激......谢谢

【问题讨论】:

  • 这看起来有点像家庭作业 - 也许先展示你的工作 - 提示你需要使用连接
  • 我会添加tbl_room.room_notes,例如'靠近电梯'(或'...电梯',如果它在另一边大西洋)或'市中心的美景'

标签: sql


【解决方案1】:

我可能会将请求的日期范围扩展到相应的日期列表中,然后根据预订记录检查列表中的每个日期以及请求类别的每个房间。

这是我的 SQL Server 解决方案,它使用 recursive CTE 来扩展日期范围:

WITH cte_datelist AS (
  SELECT @startdate AS date
  UNION ALL
  SELECT DATEADD(day, 1, date)
  FROM cte_datelist
  WHERE date < @enddate
)
SELECT
  r.room_number,
  MIN(d.date) AS free_from,
  MAX(d.date) AS free_to
FROM cte_datelist d
  CROSS JOIN tbl_room r
  INNER JOIN tbl_roomcategory rc ON r.room_categId = rc.room_categId
  LEFT JOIN tbl_reservation rr ON r.room_id = rr.room_id
  LEFT JOIN tbl_reservationdetails rd ON rr.resrvdtl_id = rd.resrvdtl_id
    AND d.date BETWEEN rd.start_date AND rd.end_date
WHERE rc.room_category = @category
  AND rd.resrvdtl_id IS NULL
GROUP BY
  r.room_number,
  DATEDIFF(day, @startdate, d.date)

此查询的另外两个特定于 RDBMS 的元素是两个日期函数:

  • DATEADD,在 CTE 中用于迭代日期范围;

  • DATEDIFF,用于对同一房间的连续日期序列上的结果集进行分组,因此而不是

    room_number  date
    1783         27/03/2011
    1783         28/03/2011
    ...          ...
    1783         02/04/2011
    1783         03/04/2011
    1785         15/03/2011
    1785         16/03/2011
    ...          
    1785         01/04/2011
    1785         02/04/2011
    1785         06/04/2011
    1785         07/04/2011
    ...          ...
    1785         10/04/2011
    ...          ...
    

    你可以有这样的输出:

    room_number  free_from   free_to
    1783         27/03/2011  03/04/2011
    1785         15/03/2011  02/04/2011
    1785         06/04/2011  10/04/2011
    ...          ...         ...
    

【讨论】:

    【解决方案2】:
    SELECT rooms.room_id
    FROM tbl_rooms rooms
    INNER JOIN tbl_roomcategory cat ON rooms.room_categId = cat.room_categId
    WHERE cat.room_category = [category]
    AND rooms.room_id NOT IN (SELECT t1.room_id
                              FROM tbl_room t1
                              INNER JOIN tbl_reservation t2 ON t1.room_id = t2.room_id
                              INNER JOIN tbl_reservationdetails t3 ON t2.resrvdtl_id = t3.resrvdtl_id
                              WHERE NOT ([end date] < t3.start_date OR ([start date] > t3.end_date))
    

    所以我会解释的。这会查找在提供的日期内不可用的任何房间。

    (SELECT t1.room_id
    FROM tbl_room t1
    INNER JOIN tbl_reservation t2 ON t1.room_id = t2.room_id
    INNER JOIN tbl_reservationdetails t3 ON t2.resrvdtl_id = t3.resrvdtl_id
    WHERE NOT ([end date] < t3.start_date OR ([start date] > t3.end_date))
    

    这会选择指定类别的所有房间。

    SELECT rooms.room_id
    FROM tbl_rooms rooms
    INNER JOIN tbl_roomcategory cat ON rooms.room_categId = cat.room_categId
    WHERE cat.room_category = [category]
    

    这会选择所有属于指定类别且不在不可用房间中的房间。

    AND rooms.room_id NOT IN (SELECT t1.room_id
                              FROM tbl_room t1
                              INNER JOIN tbl_reservation t2 ON t1.room_id = t2.room_id
                              INNER JOIN tbl_reservationdetails t3 ON t2.resrvdtl_id = t3.resrvdtl_id
                              WHERE NOT ([end date] < t3.start_date OR ([start date] > t3.end_date))
    

    我无法对此进行测试,但应该是正确的。如果有任何问题,请告诉我,我会修复它。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 2017-08-27
    • 2016-03-29
    • 1970-01-01
    相关资源
    最近更新 更多