【问题标题】:How to store a store opening hours in an SQL database?如何将商店营业时间存储在 SQL 数据库中?
【发布时间】:2021-03-05 14:26:09
【问题描述】:

我正在为商店(实际上是餐馆)开发一个应用程序,需要为其设计 PostgreSQL 数据结构。

例如,餐厅的营业时间可能为周一至周五 7:30 至 17:00 以及次日 20:30 至 1:00。

每个工作日要存储的数据类似于['Monday', true, 450, 1050, 1230, 1500 ],为真 ===“它确实在星期一开放”,450,开放时间是午夜过后 450 分钟(参见here),即在7:30h,17:30h 关闭,20:30h 重新开放,凌晨 1 点关闭(分段时间和午夜后的关闭时间在我的祖国西班牙并不少见)。当然,我可以省略前两个元素,'Monday' 和 'true',但它们可能会使前端开发更容易(例如,参见 model for data input)。

我已经确定了至少四种在 PostgreSQL 数据库中存储数据的可行选项:

1) 'restaurants' 表中的列 'opening_hours' 具有 jsonb 数据类型

[

['星期一', true, 450, 1050, 1230, 1500 ]

...

['星期天', false, 0, 0, 0, 0 ]

]

2) 表“restaurants”中每小时一列

我可能会省略上面显示的前两个元素('Monday' 和 'true')。这会在我的表中添加 7 x 4 = 28 列:

  • openMon1
  • closeMon1
  • openMon2
  • closeMon2
  • openTue1
  • ...

3) 新表“opening_hours”

使用外键 'restaurant_id' 引用表 'restaurants' 中的 'id',与 2) 的设计相同。

4) 所有 7 个工作日的数据类别列

例如,“open1”列将采用“0450-0450-0450-0450-0450-0000-0000”的形式,例如here。因此,我会像选项 1) 那样汇总数据,但我看不出后者比前一个选项有任何真正的优势。

目前,选项 1 足以满足我想要实现的业务逻辑:以与 Google 类似的方式显示营业时间,因此我认为没有任何理由足以支持 2) 或 3) 1),但我当然可能会错过未来发展的可能性。

什么数据结构遵循最佳实践?还有比这些更好的选择吗?

【问题讨论】:

  • 如果我在其中添加 days_open 表和 open_id, restaurant_id, day of week , open 。然后opening_hrshours_id, open_id, hr_start, hr_end 的表,其中hr_starthr_end 是时间字段。同样对于一天hr_end 不会超过午夜,您将在第二天的午夜开始到当天的结束时间。

标签: sql postgresql database-design database-normalization table-structure


【解决方案1】:

一种非常灵活且规范化的方法是将每个开放期间存储为表格中的一行。开放期可以编码为它开始的工作日、一天中开始的时间和持续的持续时间。每个营业时间都通过外键链接到餐厅。

CREATE TABLE opening_period
             (restaurant integer,
              weekday integer,
              time time,
              duration interval,
              PRIMARY KEY (restaurant,
                           weekday,
                           time,
                           duration),
              FOREIGN KEY (restaurant)
                          REFERENCES restaurant
                                     (id)
                          ON DELETE CASCADE,
              CHECK (weekday >= 0
                     AND weekday < 7),
              -- prevent overlapping opening periods
              EXCLUDE USING gist (restaurant WITH =,
                                  tsrange('epoch'::timestamp + time + weekday * INTERVAL '1 days',
                                          'epoch'::timestamp + time + weekday * INTERVAL '1 days' + duration,
                                          '[)') WITH &&));

【讨论】:

  • 如果您存储 start_timeend_time,排除约束会变得容易得多:dbfiddle.uk/…
  • 谢谢大家!我猜 Sticky bit 的解决方案可以使过去的午夜营业时间无需从第二天 00:00 开始求助于另一排。
  • @a_horse_with_no_name:是的,那将是另一种选择。不过,它需要第二个工作日列,以允许从午夜到第二天的开口。
猜你喜欢
  • 2011-11-09
  • 1970-01-01
  • 2020-11-14
  • 2010-10-20
  • 1970-01-01
  • 1970-01-01
  • 2014-05-31
  • 1970-01-01
  • 2018-01-18
相关资源
最近更新 更多