我正在创建一个数据库,需要允许在特定日期从开始时间到结束时间预订资源。例如,我有11个羽毛球场。这些法院可以预订1小时,也可以在一天内每天从早上6点到晚上12点进行18次预订。 (考虑每次预订是一小时)。预订价格也每天都有所不同,例如早上的费用超过了日费。周末费用超过工作日收费。
现在我的问题是,是否建议预先填充插槽,然后根据可用性为用户预订。但是在这种情况下对于abobe示例如果我需要在接下来的1个月内存储插槽,那么我将不得不提前存储11 * 18 * 30 = 5940条记录而没有任何实际预订。每个午夜我都需要运行脚本来创建插槽。如果俱乐部没有增加,这个数字会变得很大。这种系统的优秀设计是什么?如果没有,那么这些场景中的设计更好。
club name||court || date || start_time || end_time || status || charge ||
a c1 20/04/2015 6:00 7:00 available
a c1 20/04/2015 7:00 8:00 available
.
.
.
a c1 20/04/2015 11:00 24:00 available
.
.
a c11 20/04/2015 11:00 24:00 available
答案 0 :(得分:7)
现在我的问题是,是否建议预先填充插槽,然后根据可用性为用户预订。但是在这种情况下对于abobe示例如果我需要在接下来的1个月内存储插槽,那么我将不得不提前存储11x18x30 = 5940条记录而没有任何实际预订。每个午夜我都需要运行脚本来创建插槽。如果俱乐部没有增加,这个数字就会变得很大。
是。这是一种可怕的方法。由于您所说的原因,还有更多。
存储非事实是荒谬的
大量非事实的存储是不合理的
如果需要编写简单的代码是一个问题,请正确处理,提高编码技巧,这样就不会出现问题(而不是将数据库降级为原始文件系统,为了满足你的编码技巧)。
请注意,您建议的是每个法院的日历(这不是不合理的作为可视化,或作为结果集),其中大多数插槽将为空(可用)
这种系统的优秀设计是什么?
不,这太可怕了。
这不是设计。这是一个没有设计的实现。
如果没有,那么这些场景中的设计更好。
我们使用数据库。鉴于其无与伦比的地位,以及您的平台,特别是关系数据库。
我们只会存储您需要的事实,以及您需要参与的真实世界。我们需要远离可视化我们必须完成的工作(数千个日历,部分为空),并将数据视为数据,并将其视为数据。包括所有规则和约束。
在此之后,事实的确定或事实的缺失很容易。我可以为您提供您需要的关系数据库,但您必须能够编写SQL代码,以便有效地使用数据库。
试试这个:
Resource Reservation Data Model
这是一个IDEF1X数据模型。 IDEF1X是关系数据库建模的标准。请注意每一个小嘀嗒声;缺口;并标记;乌鸦脚;实线与虚线;广场与圆角;意味着非常具体和重要的东西。请参阅IDEF1X Notation。如果您不理解符号,您将无法理解或工作模型。
我已经包括:
仅存储事实(保留)。事实(可用性)的事实或缺失很容易确定。
club_resource_slot.duration
允许任何持续时间,而不是假设一小时,这可能会改变。在任何情况下都需要它,因为它划分了时间段。
resource_code,
而不是法院号码。这允许保留任何俱乐部资源(以及球场号码),而不是仅羽毛球或壁球场。您将来可能会有会议室。
Joel的回复rate
表在回答该特定问题时非常正确。我在模型的其余部分的上下文中给出了一个更简单的形式(更少规范化,更容易编码)。
如果您想要Predicates,请询问。
您似乎在编码的某些方面存在问题,我将首先讨论这些问题:
但这种方法的问题是,如果我需要根据游戏,位置,日期和时间段找到法院的可用性,那么我将不得不为所有俱乐部加载此费率表并查看实际情况预订表,如果有人已经预订了插槽。是不是更好的方法是如果我提前保留插槽然后有人预订,jst将状态更改为预订。所以该查询将完全在DB中执行,而不在内存中进行任何计算。
rate
表的存在与否,不会产生问题。这可以通过连接来完成。所描述的步骤不是必需的。
请注意,您无需加载整个表格"当然,但您可能需要加载一个表或其他表来填充您的下拉菜单等。
当有人预定法庭时,只需插入预约VALUES()
当有人取消预订时,只需删除预订VALUES()
打印保留广告位的矩阵应该很明显,很简单。
打印可用或可用加保留(您的日历视觉)矩阵需要投影。如果您不理解这种技巧,请阅读this Answer。一旦你理解了,代码就像[1]一样简单。
您需要能够对子查询和派生表进行编码。
确定插槽是保留还是可用需要简单查询。我将提供一些示例代码来帮助您。 "游戏"没有指定,我将假设位置意味着俱乐部。
IF (
SELECT COUNT(*) -- resources/courts reserved
FROM reservation
WHERE club_code = $club_code
AND date_time = $date_time
) = 0
THEN PRINT "All courts available"
ELSE IF (
SELECT COUNT(*) -- resources/courts that exist
FROM club_resource_slot
WHERE club_code = $club_code
AND date_time = $date_time
) = (
SELECT COUNT(*) -- resources/courts reserved
FROM reservation
WHERE club_code = $club_code
AND date_time = $date_time
)
THEN PRINT "All courts reserved"
ELSE PRINT "Some courts available"
请随时发表评论或提问。
答案 1 :(得分:0)
从数据维护的角度来看,提供一个有法院的表格(每个法院有1个记录)和一个有预订的表格(每个预订1个记录)可能更有效率。
BOOKING
记录应该有COURT
预订开始日期/时间和预订结束日期/时间的外键。它还可以提供有关预订人员的信息,这可能是CUSTOMER
表的外键,也可能是填写名称等,具体取决于您的业务运作方式。
答案 2 :(得分:0)
假设每次预订都是一小时(也就是说,如果有人想在法庭上花两个小时,他们每次需要两个小时的预订),在我看来,最有效的存储机制就是一张桌子{{ 1}}列Booking
,Court
和Date
(以及预订人员,付款说明等的其他列。)每次法院审核时,您都会插入一条记录预订了一个小时。
这个表格将是人口稀少的,因为只有预订的每小时单位的记录,而不是可用的单位。不会预先生成数据;你只会在预订时创建记录。
要生成每日或每周日历,您的应用程序将从数据库中检索预订的小时数,并将其与您的工作时间(早上6点至午夜)相关联,以生成法庭可用性的可视化。