我们正在为学校编写记录管理产品,其中一项要求是能够管理课程安排.我没有看过我们如何处理这个问题的代码(我现在正处于一个不同的项目中),但是我开始想知道如何最好地处理这个要求的一个特定部分,即如何处理这个事实每个课程可以在一周中的一天或多天举行,以及如何最好地将这些信息存储在数据库中.为了提供一些上下文,一个简单的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
在这个(人为的)例子中处理专栏的最佳方法是什么?我遇到的问题是,这是一个多值领域:也就是说,你可以在一周中的任何一天开设一门课程,并且可以在一天以上的时间内完成相同的课程.我知道某些数据库本身支持多值列,但假设数据库本身不支持它,是否有"最佳实践"来处理这个问题?
到目前为止,我已经提出了以下可能的解决方案,但我想知道是否有人有更好的方法:
这是我头脑中的第一件事(我不确定这是不是一件好事......).在此解决方案中,DaysOfWeek
将被定义为一个字节,前7位将用于表示星期几(每天一位).1位表示在一周的相应日期举行了一个班级.
优点:易于实现(应用程序可以处理位操作),适用于任何数据库.
缺点:更难编写使用该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
列的查询中发生了什么.
缺点:唯一真正的"骗局"是,与位域方法一样,它通过在单个字段中存储可变数量的值来打破关系模型.
另一种可能性是创建一个新表来存储一周中所有日期的唯一组合,并将该Course.DaysOfWeek
列简单地作为此查找表中的外键.然而,这个解决方案似乎是最不优雅的解决方案,我只考虑它,因为它似乎是The Relational Way TM来做事情.
优点:从关系数据库的角度来看,它是唯一的"纯粹"解决方案.
缺点:它不够优雅和繁琐.例如,您将如何设计用户界面以将相应的工作日分配到查找表周围的给定课程?我怀疑用户想要处理"星期日","星期日,星期一","星期日,星期一,星期二","星期日,星期一,星期二,星期三"等等的选择,等等...
那么,是否有更优雅的方法来处理单个列中的多个值?或者提议的解决方案是否足够?对于它的价值,我认为我的第二个解决方案可能是我在这里概述的三种可能解决方案中最好的,但我很想知道某人是否有不同的意见(或者确实是完全不同的方法).
如果我们使用bit选项,我认为编写查询并不困难.只需使用简单的二进制数学 我认为这是最有效的方法.就个人而言,我一直这样做.看一看:
sun=1, mon=2, tue=4, wed=8, thu=16, fri=32, sat=64.
现在,说这个课程是星期一,星期三和星期五.在数据库中保存的值为42(2 + 8 + 32).然后你可以在周三选择课程,如下所示:
select * from courses where (days & 8) > 0
如果你想要星期四和星期五的课程,你会写:
select * from courses where (days & 48) > 0
本文是相关的:http://en.wikipedia.org/wiki/Bitwise_operation
你可以把星期几的数字作为代码中的常量,它就足够清楚了.
希望能帮助到你.
我会避免纯度感的字符串选项:它增加了一个你不需要的额外编码/解码层.在国际化的情况下,它也可能搞砸你.
由于一周中的天数是7,我会保留七列,也许是布尔值.这也将有助于后续查询.如果该工具曾在不同日期工作周开始的国家使用,这也很有用.
我会避免查找,因为这会过度规范化.除非您的查询项目不明显或可能发生变化,否则这样做太过分了.在星期几的情况下(例如,不像美国的州),我会在固定的情况下安然入睡.
考虑到数据域,我认为bitfield不会为您节省大量空间,只会使您的代码更复杂.
最后,关于这个领域的一个警告:许多学校在他们的日程表中做了奇怪的事情,他们"交换日子"在假期期间平衡每个类型的相同数量的工作日.我不清楚你的系统,但也许最好的办法是存储一个预计课程实际日期的表格.这样,如果一周内有两个星期二,老师可以获得两次出现的报酬,而被取消的星期四的老师将不会付款.
一个可能的#4:为什么它需要是一个列?您可以为表中的每一天添加7位列.针对它编写SQL很简单,只需在您选择的列中测试1即可.从数据库中读取的应用程序代码只是将其隐藏在交换机中.我意识到这不是正常的形式,我通常会花费相当多的时间来尝试从以前的程序员那里撤消这些设计,但我有点怀疑我们将在不久的将来添加第八天.
要评论其他解决方案,如果我遇到查找表,我可能会呻吟.我的第一个倾向是带有一些自定义数据库函数的位字段,以帮助您轻松地编写针对该字段的自然查询.
我很想读一些人们想出的其他建议.
编辑:我应该添加#3,上面的建议更容易添加索引.我不确定如何编写一个SQL查询,例如"让我上周四的所有课程"来查找不会导致表扫描的#1或#2查询.但今晚我可能只是昏暗.