繁体   English   中英

SQL 调度 - 超额预订报告

[英]SQL Scheduling - Overbooked Report

我需要一种方法来查看超额预订的给定资源(在本例中为房间/床位)。 这是我的表结构。 对不起匈牙利符号:

房间
--房间ID

tblBooking
--BookingID
--开始日期
- 结束日期
--AssignedRoomID(外键)

我没有任何不工作的 SQL 可以在这里发布,因为我真的不知道从哪里开始。 我正在使用 MS Access,但如果可能的话,我正在寻找与数据库无关的解决方案。 必须更改一些关键字以匹配给定 SQL 引擎的方言是可以的,但我想避免使用其他专有功能或仅在一个 RDBMS 中可用。

我意识到最好从一开始就避免超额预订,但这不是这个问题的重点。

如果它有帮助,我几天前发布了一个相关问题,关于如何查找尚未为给定数据范围预订的资源。 你可以在这里看到这个问题。

编辑1:
在回复下面的答案时,我稍微修改了您的 SQL 以使其在 Access 中工作以及在检测冲突时更准确。 如果我错了,您在下面发布的解决方案允许与 go 发生一些冲突而不引起注意,但当给定的 Booking 的 EndDate 和不同的 Booking 的 BeginDate 落在同一天时也会显示冲突,这实际上是允许的,不应显示为冲突。 我是否正确理解这一点,或者我在这里遗漏了什么?

SELECT
  *
FROM
  tblBooking AS booking
INNER JOIN
  tblBooking AS conflict
    ON  [conflict].AssignedRoomID = [booking].AssignedRoomID
    AND (([conflict].BeginDate >= DateAdd("d", -1, [booking].BeginDate) AND [conflict].BeginDate < [booking].EndDate)
    OR  ([conflict].EndDate > [booking].BeginDate AND [conflict].EndDate < [booking].EndDate))
    AND [conflict].BookingID <> [booking].BookingID

那么,您要查找的是 tblBooking 中的任何记录,其中在重叠期间有另一条具有相同 AssignRoomID 的记录?

一个天真的解决方案是......

SELECT
  *
FROM
  tblBooking  [booking]
INNER JOIN
  tblBooking  [conflict]
    ON  [conflict].AssignedRoomID = [booking].AssignedRoomID
    AND [conflict].BeginDate     <= [booking].EndDate
    AND [conflict].EndDate       >= [booking].BeginDate
    AND [conflict].BookingID     != [booking].BookingID

最后一个条件阻止预订成为它自己的冲突。 也可以将其更改为AND [conflict].BookingID > [booking].BookingID以免重复发生冲突。 (如果 A 与 B 冲突,您只会得到A,B而不是B,A 。)


编辑

上述解决方案的问题在于它不能很好地扩展。 搜索冲突时,该房间的所有预订在预订的 EndDate 之前找到,然后根据 EndDate 过滤。 几年后,第一次搜索(希望使用索引)将返回很多很多记录。

一种优化是有一个最大的预订时长,并且只查看那么多天的冲突......

INNER JOIN
  tblBooking  [conflict]
    ON  [conflict].AssignedRoomID = [booking].AssignedRoomID
    AND [conflict].BeginDate     <= [booking].EndDate
    AND [conflict].BeginDate     >= [booking].BeginDate - 7     -- Or however long the max booking length is
    AND [conflict].EndDate       >= [booking].BeginDate
    AND [conflict].BookingID     != [booking].BookingID

通过在[conflict].BeginDate周围包裹>= AND a <= ,索引搜索现在可以快速返回合理有限数量的记录。

对于超过最大预订长度的预订,可以将它们作为多个预订输入数据库。 这就是优化艺术的用武之地,它通常都是关于权衡和妥协:)


编辑

提供不同详细信息的另一种选择是将预订加入日历表。 (例如,每天有一条记录。)

SELECT
  [room].RoomID,
  [calendar].Date,
  COUNT(*)                      AS [total_bookings],
  MIN([booking].BookingID)      AS [min_booking_id],
  MAX([booking].BookingID)      AS [max_booking_id]
FROM
  [calendar]
CROSS JOIN
  tblRoom     [room]
INNER JOIN
  tblBooking  [booking]
    ON  [booking].AssignedRoomID = [room].RoomID
    AND [booking].BeginDate     <= [calendar].Date
    AND [booking].EndDate       >= [calendar].Date
GROUP BY
  [room].RoomID,
  [calendar].Date
HAVING
  COUNT(*) > 1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM