一尘不染

在关系数据库中存储事件发生的星期几的最佳方法是什么?

sql

我们正在为学校编写记录管理产品,其中一项要求是能够管理课程表。我没有看过如何处理此代码(目前我在一个不同的项目中),但是我开始想知道如何最好地处理此要求的一个特定部分,即如何处理以下事实:每门课程一周可以举行一或几天,以及如何最好地将这些信息存储在数据库中。为了提供一些上下文,准系统Course表可能包含以下几列:

Course          Example Data
------          ------------

DeptPrefix      ;MATH, ENG, CS, ...
Number          ;101, 300, 450, ...
Title           ;Algebra, Shakespeare, Advanced Data Structures, ...
Description     ;...
DaysOfWeek      ;Monday, Tuesday-Thursday, ...
StartTime       
EndTime

我想知道的是,DaysOfWeek在此(人为)示例中处理列的最佳方法是什么?我遇到的问题是一个多值字段:也就是说,您可以在一周的任何一天开设一门课程,而同一课程可以在一天以上进行。我知道某些数据库本机支持多值列,但是假设数据库本身不支持多值列,是否有“最佳实践”来处理呢?

到目前为止,我已经提出了以下可能的解决方案,但是我想知道是否有人有更好的选择:

可能的解决方案1:将DaysOfWeek视为位字段

这是突然出现在我脑海中的第一件事(我不确定那是否是好事…)。在此解决方案中,DaysOfWeek将被定义为一个字节,并且前7位将用于表示星期几(每天一位)。1位表示该课程是在一周的相应日期举行的。

优点 :易于实现(应用程序可以处理位操作),可以与任何数据库一起使用。

缺点
:很难编写使用该DaysOfWeek列的查询(尽管您可以在应用程序级别处理此问题,或者在数据库中创建视图和存储过程来简化此操作),这会破坏关系数据库模型。

可能的解决方案2:将DaysOfWeek存储为字符串

这本质上与使用位字段的方法相同,但是无需处理原始位,而是为一周中的每一天分配一个唯一的字母,并且该DaysOfWeek列仅存储一系列字母,指示课程的开设日期。例如,您可以将每个工作日与单个字符代码相关联,如下所示:

Weekday      Letter
-------      ------

Sunday       S
Monday       M
Tuesday      T
Wednesday    W
Thursday     R
Friday       F
Saturday     U

在这种情况下,当然举行周一,周二和周五将有具有价值'MTF'DaysOfWeek,而只有在周三召开班会拥有DaysOfWeek的价值'W'

优点
:更易于处理查询(即,您可以使用INSTR,或类似的方法来确定某个课程是否在给定的日期举行)。可与支持INSTR或等效功能的任何数据库一起使用(我想大多数是…)。看起来也更友好,而且一目了然,可以轻松查看使用该DaysOfWeek列的查询中发生了什么。

缺点 :唯一真正的“ 缺点 ”是,就像位域方法一样,这通过在单个字段中存储可变数量的值来破坏关系模型。

可能的解决方案3:使用查找表(难看)

另一种可能性是创建一个新表,该表存储一周中各天的所有唯一组合,并使该Course.DaysOfWeek列只是该查找表中的外键。但是,此解决方案似乎是最不雅致的解决方案,我之所以只考虑它,是因为它看起来像是The
Relational Way TM做事情。

优点 :从关系数据库的角度来看,这是唯一“纯”的解决方案。

缺点
:笨拙而且繁琐。例如,您将如何设计用于为查找表周围的给定课程分配相应工作日的用户界面?我怀疑用户是否希望按照“星期日”,“星期日,星期一”,“星期日,星期一,星期二”,“星期日,星期一,星期二,星期三”等来处理选择……

还有其他想法吗?

那么,有没有更优雅的方法可以在单个列中处理多个值?或提议的解决方案之一就足够了吗?就其价值而言,我认为我的第二种解决方案可能是我在此处概述的三种可能的解决方案中最好的一种,但是我很想知道某人是否有不同的看法(或者完全是另一种方法)。


阅读 186

收藏
2021-03-17

共1个答案

一尘不染

从纯粹的意义上讲,我会避免使用string选项:它增加了您不需要的额外编码/解码层。在国际化的情况下,它也可能使您不知所措。

由于一周中的天数是7,因此我将保留7列,可能是布尔值。这也将便于后续查询。如果该工具曾经在工作周在不同日期开始的国家/地区使用过,则这也将很有用。

我会避免查找,因为那样会导致过度规范化。除非您的查找项目集不明显或可能会更改,否则它是过大的。如果是一周中的几天(例如,与美国各州不同),我会在固定的情况下安然入睡。

考虑到数据域,我认为位域不会为您节省大量空间,只会使您的代码更复杂。

最后,一个关于领域的警告:许多学校在他们的日程安排上做一些奇怪的事情,他们“交换日”以平衡整个学期中每种类型的平日数量,尽管有假期。对于您的系统,我尚不清楚,但是最好的方法也许是存储一张表中预计要上课的实际日期的表。这样,如果一周中有两个星期二,老师可以因两次出现而获得报酬,而被取消的星期四的老师将不会获得报酬。

2021-03-17