我正在为商店(实际上是餐馆)开发一个应用程序,并且需要为其设计PostgreSQL数据结构。
例如,餐厅的营业时间可能为周一至周五的7:30至17:00,以及第二天的20:30至1:00。
每个工作日要存储的数据将是这样的['Monday', true, 450, 1050, 1230, 1500 ],为true ===“它确实在星期一营业”,450,营业时间是午夜之后的450分钟,即7:30h,在17:30时关闭: 30h,在20:30h重新开放,并在凌晨1点关闭(午夜后的休息时间和关闭时间在我的祖国西班牙并不罕见)。当然,我可以省去前两个元素“ Monday”和“ true”,但是它们可能会使前端开发更加容易(例如,参见数据输入模型)。
['Monday', true, 450, 1050, 1230, 1500 ]
我已经确定了至少四个可行的方法来将数据存储在PostgreSQL数据库中:
1)“餐厅”表中具有“ jsonb”数据类型的“ opening_hours”列
[
[‘Monday’,true,450、1050、1230、1500]
…
[‘Sunday’,false,0、0、0、0]
]
2)表格“餐厅”中每小时一栏
我可能会忽略上面显示的前两个元素(“星期一”和“真实”)。这将在我的表中添加7 x 4 = 28列:
3)新表“ opening_hours”
在表“ restaurants”中使用外键“ restaurant_id”引用“ id”,其设计与2)相同。
4)所有7个工作日的数据类别列
例如,列’open1’将采用‘0450-0450-0450-0450-0450-0000-0000’的形式,因此,我将像选项1中那样聚合数据,但是与前一种选项相比,我看不出后者有任何真正的优势。
就目前而言,选项1足以满足我要实现的业务逻辑:以类似于Google的方式显示营业时间,因此我看不出有什么理由足以让2)或3)胜过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 &&));