在数据库中存储营业时间

use*_*000 76 database database-design

我目前正在尝试找出在数据库中存储业务小时数的最佳方法.

例如:

业务A有以下营业时间

  • 星期一:上午9点到下午5点
  • 周二:上午9点至下午5点
  • 周三:上午9点至下午5点
  • 周四:上午9点至下午5点
  • 星期五:上午9点至下午5点
  • 周六:上午9点至中午12点
  • 星期日:休息

目前我有一个类似于以下的数据模型

CREATE TABLE "business_hours" (
    "id" integer NOT NULL PRIMARY KEY,
    "day" varchar(16) NOT NULL,
    "open_time" time,
    "close_time" time
)
Run Code Online (Sandbox Code Playgroud)

其中"日"仅限于代码中一周7天的选择(通过ORM).要测试某个企业是否在某一天关闭,它会检查open_time和close_time是否为NULL.它通过中间表(多对多关系)与业务相关.

有没有人对这个数据库方案有任何建议?关于它的一些事情对我来说似乎并不合适.

Fra*_*ger 50

总的来说,我认为这没有错.除了...

  1. 我会使用您的本机编程语言使用的任何编号系统(在其库中)将星期几存储为整数.这将减少数据库的大小并从代码中删除字符串比较.

  2. 我可能会将外键放在此表中的业务表中.这样你就不需要链接表了.

所以我想我会这样做:

CREATE TABLE "business_hours" (
     "id" integer NOT NULL PRIMARY KEY,
     "business_id" integer NOT NULL FOREIGN KEY REFERENCES "businesses",
     "day" integer NOT NULL,
     "open_time" time,
     "close_time" time
)
Run Code Online (Sandbox Code Playgroud)

在我的业务逻辑中,我会强制执行约束,即每个"业务" 至少有 7个"营业时间".(至少因为Jon Skeet是对的,你可能想要休假时间.)虽然你可能想要放松这个限制,只需在业务关闭的几天内停止"营业时间".

  • 我会说是的.否则,考虑如果两个企业碰巧共享相同的时间会发生什么,但其中一个需要改变他们的工作时间.您必须检测小时数已更改的事实,并创建新记录或编辑现有记录,具体取决于是否共享. (7认同)
  • 我绝对不会在企业之间分享这个表的行.这种分享只会导致痛苦.应用程序的业务逻辑应该强制执行每个企业至少有7个"business_hours"引用的约束. (3认同)
  • 一家每天营业超过一家的餐厅怎么样?例如周一上午 10 点至下午 2 点和周一下午 5 点至晚上 10 点(仅在午餐和晚餐期间营业)。您的数据库架构将如何支持这一点?我们如何在数据库中创建如此灵活的数据结构? (2认同)
  • 查看 http://schema.org/OpeningHoursSpecification 将是最好的。它们包括 validFrom 和 validThrough 日期,这对于有夏季和冬季营业时间的企业或商店来说非常常见 (2认同)

dav*_*don 22

此架构未涵盖的一种情况是一天中的几个开放时段.例如,当地酒吧的营业时间为12:00-14:30和17:00-23:00.

也许剧院售票处可以进行日场演出和晚间演出.

此时,您需要决定同一天是否可以有多个条目,或者是否需要在同一行中表示不同的小时数.

那个跨越午夜的开放时间怎么样?比如说酒吧营业时间为19:00-02:00.您不能只将开始和结束时间与您要测试的时间进行比较.

  • 哪种方式可以节省这种开放时间?有什么建议吗? (3认同)
  • 这就是我来这里的原因.要尝试一种解决方案,将开放和关闭时间保存为不同的实体,然后通过查看最近发生的任何更改来确定给定的业务是否"开放".思考? (2认同)

Fra*_*ans 10

它取决于您需要存储的内容以及实际数据的外观.
如果您需要能够确定业务是否在某个时间点开放,那么查询该方案可能有点尴尬.更重要的是,您是否需要迎合中午关闭?

一些选项包括;

  • 一个类似你所拥有的计划,但可以选择在同一天有多个期间.它可以满足午休时间的需要,但是会让你查看给定的一天的开放时间,比如向用户展示,这会让你很尴尬.
  • 位图风格的方法; 9-5的"000000000111111110000000".这种方法的缺点是你必须选择一个特定的粒度,即整个小时或半小时,或者实际上是分钟.粒度越精细,人类就越难读取数据.您可以使用按位运算符将此值存储为单个数字而不是整数字符串,但同样会损害易读性.


CTS*_*_AE 9

我了解到,如果您想让Google数据标记识别您的数据,您应该遵循以下准则:

https://schema.org/openingHours

http://schema.org/OpeningHoursSpecification包含"有效日期",这对某些企业非常有用.

https://schema.org/docs/search_results.html#q=hours

没有主键你应该没问题,除非你允许企业与联盟表共享相同的时间 - 有趣的是最终你将拥有有限数量的组合; 我不确定会有多少:p

在我的一个项目中,我使用了列:

[uInt] business_id,[uTinyInt] day,[char(11)] timeRange

如果您想支持OpeningHoursSpecification,则需要添加validFrom和validThrough.

时间范围的格式如下:hh:mm-hh:mm

这是一个解析它的函数,如果将它们作为DB中的单独列保存,您也可以修改此函数以解析单个打开/关闭.

根据我的经验,我建议您在一天内允许多次,允许告诉他们当天是明确关闭,还是24小时或24/7开放.我曾经说过,如果数据库中缺少一天,那么业务当天就关闭了.

/**
 * parseTimeRange
 * parses a time range in the form of
 * '08:55-22:00'
 * @param $timeRange 'hh:mm-hh:mm' '08:55-22:00'
 * @return mixed ['hourStart'=>, 'minuteStart'=>, 'hourEnd'=>, 'minuteEnd'=>]
 */
function parseTimeRange($timeRange)
{
    // no validating just parsing
    preg_match('/(?P<hourStart>\d{1,2}):(?P<minuteStart>\d{2})-(?P<hourEnd>\d{1,2}):(?P<minuteEnd>\d{2})/', $timeRange, $matches);

    return $matches;
}
Run Code Online (Sandbox Code Playgroud)


Mah*_*sem 8

大多数结果对于给定的场景都可以正常工作,但如果您的经期持续多天,例如,它就不会那么有效。8:00 AM ~ 2:00 AM,那么我建议使用多时段设计。

    {
         id: 1,
         day: 1,
         periods: [
             0: { open: 08:00, close: 00:00 }
         ]
    },
    {
         id: 2,
         day: 2,
         periods: [
             0: { open: 08:00, close: 00:00 }
             1: { open: 00:00, close: 02:00 }
         ]
    }
Run Code Online (Sandbox Code Playgroud)

day : 一周中的第几天,
如果没有句号,则表示休息