簡體   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