我正在做一个大厅预订系统,我一直在努力解决预订模块的问题
我有两张表Halls
和Bookings
带样本数据的霍尔斯表
id hallName hallType numSeats status
---------------------------------------------
1 Hall 1 Normal 500 active
2 Hall 2 VIP 30 active
3 Hall 3 VVIP 5 active
4 Hall 4 Normal 60 active
5 Hall 5 Normal 80 active
6 Hall 4+5 Normal 140 active
样本数据预订表
id custId hallId beginDate endDate time status
-----------------------------------------------------------------
1 1 1 2022-09-26 2022-09-26 morning confirmed
2 6 4 2022-09-26 2022-09-26 evening cancelled
3 4 3 2022-09-26 2022-09-26 full time pending
4 9 4 2022-09-26 2022-09-30 after noon confirmed
预约时间为“上午”、“中午”、“晚上”和“全天”。
我一直在尝试预订验证以及一份显示大厅预订情况的报告
编辑
在我编辑并删除了第二部分的评论中的建议后,如果我想不出来,可能会单独发帖
这就是我想要的结果
可以按结束日期筛选记录(例如2022-09-26)
如果存在未取消提供的BeginDate的预订,则应将该时间段标记为Booked
如果不存在所提供的BeginDate或其已取消的预订,则应将该时间段标记为Available
如果full time
预订插槽指定用于提供的BeginDate,则这3个插槽应始终标记为Booked
以下是可能使事情复杂化的转折
从Halls table
可以看到,6号厅是4号厅和5号厅的组合,这意味着如果其中任何一个厅被预订,6号厅应该标记为unavailable
,甚至Booked
也可以。
总体而言,以下是基于上述预订表的示例结果
hallName hallType morning after noon evening
------------------------------------------------------
hall 1 Normal Booked available available
hall 2 VIP available available available
hall 3 VVIP Booked Booked Booked
hall 4 Normal available Booked available
hall 5 Normal available available available
hall 6 Normal available unavailable available
如果我们使用带有样例数据的Booking
表,结果应该如下所示
我对联合、合并等我认为的解决方案并不是很熟悉。我尝试了在匹配时和不匹配时合并,但无法解决问题
然后我试着向左连接霍尔斯的table和预订的table,这似乎是到目前为止最接近的,结果很清楚。
DECLARE @date NVarchar(50) = '2022-09-26'
SELECT h.id, h.hallName, h.hallType, b.time FROM Halls h LEFT JOIN
Bookings b ON b.hallId=h.id WHERE b.beginDate=@date
这将仅返回带有该日期的预订大厅
如果删除WHERE
子句,则所有6个大厅都将返回,但未预订的时段将作为NULL
返回
顺便说一句,我正在处理最后一个模块,起初我使用的是单一签入日期和需求范围beginDate
&endDate
&也就是出现问题的时候。
2条答案
按热度按时间wfveoks01#
首先,您需要修改您的设计,您打算如何存储
Hall 6
是Hall 4 + 5
组合的信息一种简单的方法是在
Halls
表中添加另一列来指示这一点。示例一旦放置到位,您需要平移
Bookings
以处理合并的大厅。这是由CTEBookingData
执行的。如果Hall 4
或Hall 5
是pending
或confirmed
,它将为Hall 6
创建行。同样,反过来也是如此。当Hall 6
为Booked
时,Hall 4
和Hall 5
将不可用。在此之后,只需简单地旋转数据
解决方案:
db<>fiddle demo
2hh7jdfx2#
您的问题非常复杂,因为表没有正确地实现“组合大厅”的规范化。我们需要使用字符串操作分离
Hall 4+5
,然后将提取的信息存储在某个位置。以下是我能想到的问题:你可以在小提琴上试一下:https://dbfiddle.uk/baQyI1Y7
它看起来有点可恶,我相信其他人可以写出更短的查询。
上面的查询使用了4个CTE,其中3个处理提取相关“组合大厅”的e1d1d1。
composite_halls
将从hallName
中提取数字,并将它们放入id1
和id2
中。singular_halls
将把对方的id放在id1
或id2
中,将其组合放在id3
中。all_halls
将两个结果合并为一个。valid_bookings
筛选给定时间范围的bookings
,并且仅获取confirmed``bookings
。下一步,它检查
all_halls
条目中是否有任何bookings
‘hallId
对应于id
、id1
、id2
、id3
中的任何一个。到目前为止,它只处理morning
预订,并且只提供booked
和available
状态。您可以通过添加更多case when
来扩展它以提供unavailable
,以专门处理id1
到id3
。您可以通过更改case when
子句中的time
参数,以相同的方式处理after noon
和evening
。我不认为上面的查询对于实时应用程序来说性能足够好。特别是我们逐行运作的事实,是从“合并”的大厅中提取相关的大厅。
我相信,如果你把table正常化一点,事情会容易得多。我觉得这就像用TSQL做EXCEL一样,这看起来不太对。