【问题标题】:Store 2-dim table of attendance in database?在数据库中存储二维考勤表?
【发布时间】:2009-10-03 12:42:02
【问题描述】:

我们有一个基于 Web 的应用程序,由 MySQL 数据库支持。

我们正在编写的系统的一部分要求我们将一周中每一天的用户出席情况(即是/否)存储到会话中。例如,我们需要存储周一到周五,然后是每天早上、午餐、下午、晚上的时段等。所以本质上它是一个 2-dim 数组。

我想知道在数据库中存储这个最干净的方法是什么?

目前,从事此工作的人似乎倾向于将其存储为每天的一个 int,1 代表出席,0 代表不出席。我认为这样做的意思是使用位掩码(例如 13 表示 1101,所以除了下午之外的每个会话)。出于某种奇怪的原因,他们只是将其存储为实际的 0 和 1。

我认为将其存储为布尔列表(位/小整数)可能更容易,例如monday_morning、monday_lunch、monday_afternoon 等,因为它在语义上更“正确”(我认为?),它可能更容易扩展/维护,而且我似乎也是团队中唯一一个知道如何做位操作...大声笑。

我想的另一种方法是为每个用户提供一个 1:1 的表格,例如,列出他们正在参加的所有时间。这种方法的效率? (不确定是哪种读/写模式,但我猜读/修改的分布相当均匀)。

对此有什么建议?还是有更好的方法来存储这些数据?

另外,作为旁注,它可能是布尔值 - 值得怀疑的是,我们需要在表中存储比参加/不参加更多的状态,如果我们这样做,我们准备重新 -工作模式。还是人们强烈建议使用整数而不是位?

干杯, 维克多

【问题讨论】:

    标签: database


    【解决方案1】:

    我会将它标准化并拥有三个表:users、sessions 和 session_attended。用户将包含有关用户的信息,会话将包含有关会话的信息,并且 session_attended 将是一个连接表,指示用户参加了哪些会话。正确索引您的表,生成的连接应该非常有效。

     select users.name, sessions.name
     from users u join sessions_attended a on u.user_id = a.user_id
          join sessions s on s.session_id = a.session_id
     where sessions.course = ...some course id...
    

    【讨论】:

    • 嘿嘿,唯一的问题是,与这里和那里相比,用户实际上更有可能参加所有会议,或者长时间连续参加。基本上,这就像一个为期五天的会议,例如,大多数人会一整天都去,或者迟到一天,或者提前半天离开。我们真的只需要存储是/否出席。不过,您仍然建议我们使用连接表方法吗?谢谢,维克多
    • 我的感觉是你规范化,直到规范化成为问题。
    【解决方案2】:

    您的第二种方法(单个列)“更正确”,因为它不违反第一范式。位掩码方法确实如此,因为您在单个列中存储了多个值(您正在存储多个会话的值)。

    并且不要在内部存储bit。在tinyint 上,您不会看到存储有任何减少(引擎不会为您分配一个位,它只会限制可接受的值)。您不妨使用tinyint 并给自己一些喘息的空间。

    编辑

    正如 Mark 所指出的,如果您有多个 bit 列,它可以将它们打包成一个字节,但担心数据占用一个字节还是四个字节可能是过早的优化。最标准化的解决方案是建议的解决方案,其中您有一个单独的表格,指示参与者参加了哪些会议。如果您的会话确实是固定的,那么我可能会通过位掩码或完全规范化的解决方案为每个会话设置单独的列。

    1. 位掩码会混淆数据并需要按位运算(显然)。这些在查询语法中可能会造成混淆,因为您正在多次使用单词orand。这种方法也无法编入索引,因此要查找所有参加过(例如,早上或早晚会)的参与者,每次都需要进行表格扫描。

    2. 完全规范化的解决方案会使数据查询复杂化。虽然它支持索引,但对于您要检查的每种会话类型,它都需要完全连接。

    每个会话一列的方法似乎是最好的解决方案。您仍然只处理一行数据,但您也可以使用有意义的语法进行查询并利用索引。

    【讨论】:

    • Sybase(因此我怀疑 MS SQL Server)确实在一个字节中存储了多达 8 位列,因此您确实可以获得存储优势
    • 嘿,是的,我的理解是很多 RDBMS 无论如何都会将连续的位打包在一起。如果是这样,tinyints 仍然是要走的路吗?不过,我并不是真正的 DB 人。你会推荐使用位掩码方法吗?我在数据库中使用它们的经验较少 - 在代码中,如果适合我需要运行的读/写类型,我会使用它,所以从这方面来说,我想它在这里很有用 - 但是,它真的完成了吗数据库中有很多?还是其他方法(例如上面的 tvanfosson 建议)更正确/更有效,更常见?干杯,维克多
    猜你喜欢
    • 2019-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-12
    • 2013-12-03
    相关资源
    最近更新 更多