数据库关系设计 - 在不同的表中将两个表关联两次

时间:2010-11-08 20:09:20

标签: sql-server design-patterns database-design

我有以下表格:

Post
Id int

User
Id int

然后我有桌子

Favorite
PostId int
UserId int

和表格

Vote
PostId int
UserId int
IsUpVote bit
IsDownVote bit
LastActivity datetime2

问题是,如果我将收藏夹和投票合并到一个表中,那么我会有类似

的内容
UserPost
PostId int
UserId int
IsFavorited bit
IsUpVoted bit
IsDownVoted bit
LastActivity datetime2

IsDownVote无法再计算(从现在开始,我不能使用“不存在:没有投票;没有投票:投票结果”模式了)和{{ 1}}仅反映投票最后一次更改(向上,向下或删除)。所以我可能不得不改变该字段的名称或它的功能。甚至两个..

所以问题基本上是,在这种情况下,有两个表关联表A和B LastActivity有多么错误,在这种情况下由相同的主键(Post,User)索引,但是这些表是预期的用于不同的用途?

3 个答案:

答案 0 :(得分:2)

收藏夹和投票似乎是两个不同的东西,所以恕我直言,你最好将它们作为单独的表保存。正如您所提到的,如果合并它们,您将失去功能,并且我没有看到合并它们的任何明显好处。坚持你所拥有的,除非你能为合并提供 awesome 理由。

答案 1 :(得分:1)

没有错。

我并不是说提供的DDL显示正确的规范化表,但它们有些规范化。正如你已经确定的那样,这两个表有不同的用途,它们有不同的含义,所以从技术上讲(理论上,学术上和实践中[代码]),它们是正确的。

  • “与同一父母有关”不是一个标准(有许多情况下,有很多表与同一父母有关,哪些是正确的)
  • 因此这些表格“具有相同的PK和FK”,因此这也不是一个标准。

只有没有真正归一化概念的人,并且没有负面表现原因的概念,才会暗示“只是因为他们拥有相同的父母(因此同一对密钥/指数)”,他们应该合并

投票和收藏是两个不同的事物,实体,采取的行动记录。两个表是正确的。

区别:IsDownVoted无法比较的真正原因是它不适用于收藏夹。您已使用指示符(位)来识别(尽管名称不当);这实际上是Null列的替代品。 Nulls对性能不利,并且你有一个很好的东西,你有指标来识别数据的缺失,因此避免了Nulls,但这与通过对它们打破标准化设计是分开的。

合并表在所有访问中执行速度较慢。当您从中选择投票时,您必须排除收藏夹,反之亦然,但它将为两者执行I / O,因为它们位于一起(PostId,UserId)。所以服务器永远读取两倍的行,使用两倍的缓存;然后你将通过为(PostId,UserId,IsFavourited)添加索引来“加速”,使插入和删除更慢(当“加速”选择时)。 Messes得到复合,保证;最好不要在第一时间弄乱。

当数据库增长时,您可以独立地向Vote和Favorite中的任何一个添加列,而不会影响另一个。在合并表中,它将引入复杂性。

你太快接受答案了。

答案 2 :(得分:-1)

虽然如果使用int而不是bit并使用0 1和-1之类的值进行计算/比较,我不会说明你应该做什么,这样你就可以用相对简单的方法计算你想要的值方式。

谈论关系数据库时,你几乎应该总是针对你的桌子的第3种正常形式 - 试着看http://en.wikipedia.org/wiki/Database_normalization

干杯!