【问题标题】:Hotel reservation system: How to store individual price for each night of a reservation?酒店预订系统:如何存储每晚预订的单独价格?
【发布时间】:2012-02-20 18:54:48
【问题描述】:

我有您期望的标准表格,例如“房间”、“预订”等。目前所有内容都在关系数据库中。

“预订”表存储诸如 room_id、入住日期和退房日期等项目。

现在,简而言之,当进行预订时,系统会根据“RoomPrice”表检查并获取每晚预订的费用(取决于日期、入住人数等) - 费用可能会有所不同每晚取决于当前价格。
显然,当预订时,每晚的价格都是固定的。因此,即使房价在事后更新,该预订仍将保持在商定的价格,就像在价格变化之前进行的那样。

我的问题是:我应该如何存储这些个人,在预订时为每晚商定的价格?

我正在考虑使用另一个表“PriceForNight”,它将存储预订的每一晚的预订 ID、价格和日期。

我看到的唯一可能的问题是可扩展性。如果平均预订时长为 5 晚,这意味着“PriceForNight”表的增长速度将比“预订”表快 5 倍。

“PriceForNight”数据是否会更好地存储在 NoSQL 数据库或类似数据库中?

正在考虑的另一个选项是将每晚的价格作为逗号分隔的字符串存储在“预订”表行中的单个列中,例如:“150.00,175.00,175.00,200.00,150.00”表示 5夜间预订。

我可能想多了,因为真正的问题可能只有在增长速度快 1000 倍时才会存在,但我喜欢做正确的事情,所以我想我会与社区联系。

非常感谢任何意见。

【问题讨论】:

  • 既然您要在该表中为每晚输入一个条目,为什么不将这些数据存储在预订表中呢?您可以添加两列,机架率和实际率。
  • @MarkKram 无论有多少晚,“预订”表中的每个预订都只有一个条目。

标签: mysql sql-server database database-design relational-database


【解决方案1】:

纯粹的关系方法是有一个 ReservationNight 表,该表存储有关预订每晚的详细信息,包括价格。是的,表格会快速增长,但无论您如何存储价格,数据都会快速增长。

【讨论】:

  • 感谢您的意见。所以我的“PriceForNight”表和你建议的一样吗? “reservation_id”、“价格”和“日期”?
  • 是的,尽管我假设它可能不仅仅是存储的价格。关键是您需要为每晚的预订存储信息,因此将表命名为 ReservationNight。如果它只有一个有趣的列(价格),那就这样吧,那不应该出现在表的名称中。
  • 我完全理解。感谢您的宝贵时间。
【解决方案2】:

通常,逗号分隔的列表不属于 SQL 数据库。我会说你最好的选择是连接表。

StackOverflower Bill Karwin 在这里回答得最好:Is storing a comma separated list in a database column really that bad?

除了违反First Normal Form之外,因为 存储在单个列中的重复值组,以逗号分隔 列表还有很多其他更实际的问题:

  • 无法确保每个值都是正确的数据类型:没有办法防止1,2,3,banana,5
  • 无法使用外键约束将值链接到查找表;无法强制执行参照完整性。
  • 无法强制唯一性:无法阻止1,2,3,3,3,5
  • 如果不获取整个列表,则无法从列表中删除值。
  • 很难搜索列表中具有给定值的所有实体;您必须使用低效的表扫描。
  • 很难计算列表中的元素,或进行其他聚合查询。
  • 很难将这些值加入到它们引用的查找表中。
  • 很难按排序顺序获取列表。

要解决这些问题,您必须编写大量应用程序代码, 重新发明 RDBMS 已经提供的功能更多 高效

逗号分隔的列表是错误的,我把它作为第一个 我书中的章节:SQL Antipatterns: Avoiding the Pitfalls of Database Programming.

有时您需要使用非规范化,但作为@OMG 小马提到,这些都是例外情况。任何非关系 “优化”以牺牲其他用途为代价使一种类型的查询受益 数据,因此请确保您知道哪些查询需要 受到如此特殊的对待,以至于它们应该被非规范化。

【讨论】:

  • 我以前没见过这个答案,谢谢。逗号分隔的想法肯定已经过时了。
【解决方案3】:

您可以使用日期范围而不是固定日期。

所以如果我预订:

Night 27 01 2012: 20 $
Night 28 01 2012: 20 $
Night 29 01 2012: 30 $

在数据库中:

reservationId from     to        price
5457848       20120127 20120128  20
5457848       20120129 20120129  30

如果每天都有不同的价格是很常见的,这不会减少行数。但它是非常罕见的,然后它会最多减少到 1 行。

【讨论】:

  • 我们之前也考虑过这一点,但认为每次需要显示价格时必须解构数据会产生大量处理开销。此外,如果我们希望生成财务报告或进行分析,那么单独的夜晚很可能是最容易的。
  • 那么您确实应该使用新表。它是最佳实践,它将创建更多行。如果您选择所有夜晚的费用相同并且您在该行中设置费用,则您可以在主要预订中放置一个标志。如果不是,请参阅另一张表。
  • 也是一个好建议。我们会考虑到这一点。感谢您的宝贵时间。
【解决方案4】:

一张存储每晚费用的表格,每晚一行似乎是明智的。

每个房间一年最多可租用 365 晚。 (在现实世界中,这几乎是真的。汽车旅馆业务实际上比看起来更复杂。)

如果您有 200 个房间,那么您会看到大约 200 * 365 行,即每年 73,000 行。 (我的算法做对了吗?)按照这样的速度,如果技术根本没有改进,您不必考虑担心 SQL dbms 的性能至少 100 年。

您可能还会发现this answer 很有用。它遵循相同的思路。

【讨论】:

  • 感谢您的回复。单独的表格方法对我们来说是最容易实现的,所以听到这样的说法让人放心。
  • @Alex: This SO answer 遵循同样的思路。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-27
  • 1970-01-01
  • 1970-01-01
  • 2016-09-23
  • 1970-01-01
  • 2011-01-28
  • 2019-03-02
相关资源
最近更新 更多