首页 > 解决方案 > 如何将商店营业时间存储在 SQL 数据库中?

问题描述

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

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

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

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

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

[

['星期一',真,450、1050、1230、1500]

...

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

]

2) 表“餐厅”中每小时一列

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

3) 新表“opening_hours”

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

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

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

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

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

标签: sqlpostgresqldatabase-designdatabase-normalizationtable-structure

解决方案


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

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 &&));

推荐阅读