存储重复字段:好或坏

时间:2016-09-23 07:34:15

标签: mysql postgresql database-design

假设用户有这样的帖子表:

enter image description here

帖子 id = 1 是用户发布的第一篇帖子。发布 id = 2 - 是对帖子进行的编辑, id = 3 - 帖子的最新版本。

post_param_a 不能在整个版本中更改,也不能在 user_id 中更改 - 自第一个版本以来,它们始终保持不变。所以我们可以像这样存储它:

enter image description here

所以问题是:以第二种方式存储它会更好吗?没有重复?这样,要获得当前版本的用户帖子,我们必须加入第一个版本并始终检查其 user_id 或者在这种情况下是否可以存储重复的字段?

P.S。这是有问题的,因为我们希望避免在整个版本中无法更改的值的重复和事故更改,因此我们希望将它们全部存储在一个位置

3 个答案:

答案 0 :(得分:1)

您可以在一个单独的表中为每个post_param_a存储post_id,然后您就不需要具有NULL值或重复值。

答案 1 :(得分:1)

获取实体Post并查看简单元组:

ID  User_ID  Post_Param_A  Comment
 1       69           foo  This is a post

这完全正常化了。但是,帖子可能会进行编辑,您希望跟踪所做的更改。因此,您添加另一个字段来跟踪更改。但是,添加日期时间字段会更有意义,而不是增量值。

ID  EffDate       User_ID  Post_Param_A  Comment
 1  1/1/16 12:00       69           foo  This is a post

这有两个好处:1)如果你跟踪这些变化,无论如何你都会想知道这个版本的保存时间2)你不必找到帖子的最大增量值来找出什么每个新版本保存的值。只需保存当前日期和时间。

但是,无论是增量值还是日期,都存在问题。在简单行中,每个字段都具有对PK的函数依赖性。在版本行中,User_ID和Post_Param_A保持对PK的依赖,但Comment现在依赖于PK EffDate。

元组不再是2nf。

因此,解决方案只是简单化它:

ID  User_ID  Post_Param_A
 1       69           foo

ID  EffDate        Comment
 1  1/1/16 12:00  This is a post
 1  1/1/17 12:00  An edit was made
 1  1/1/17 15:00  The last and current version (so far)

使用(ID,EffDate)新表中的复合PK。

阅读最新帖子的查询有点复杂:

select  p.ID, v.EffDate, p.User_ID, p.Post_Param_A, v.Comment
  from  Posts p
  join  PostVersions v
    on  v.ID = p.ID
   and  v.EffDate = (
        select  Max( v1.EffDate )
          from  PostVersions v1
         where  v1.ID = p.ID
           and  v1.EffDate <= today )
   and  p.ID = 1;

这并不像它看起来那么复杂,而且速度非常快。真正干净的功能是 - 如果你更换&#34;今天&#34;比如说,1/1/17 13:00,结果将是第二个版本。因此,您可以使用相同的查询查询当前或过去。

通过从&#34;今天&#34;创建一个视图来实现另一个简洁的功能。查询最后一行(&#34;和p.ID = 1&#34;)已删除。此视图将公开所有帖子的最新版本。在视图上创建触发器,这使得只对当前版本感兴趣的应用程序可以在不考虑底层结构的情况下完成工作。

答案 2 :(得分:0)

第一个解决方案更好,因为user_idpost_id保持一致并避免各种解释。

  

这样,要获取当前版本的用户帖子,我们必须加入第一个版本并一直检查其user_id。

您是否考虑添加字段timestamp,以便始终可以获得帖子的最新版本?

在第二个解决方案中, NULL 在数据增长时可能不明确。即使查询也很困难,每个SQL都应该设计好来考虑 NULL 案例及其具体含义。

第三种解决方案可以是使用2个分隔的表格对表格进行标准化,例如: postpost_history。正如您在问题中提到的post_param_a无法在整个版本中更改,以及user_id - 从第一个版本开始,它们始终保持不变。在这种情况下,

  • 在表格post中,您可以存储与帖子相关的永久性信息(不会更改):idparam_auser_id,{{ 1}} ...
  • 在表格created_at中,您可以存储与帖子相关的与每个版本/修改相关的信息:post_historyversion_idcomment ...并且您可以为第二个表添加一个FK约束,表示modified_at