加入数据透视表与复制列

Posted

技术标签:

【中文标题】加入数据透视表与复制列【英文标题】:Joining pivot table vs. duplicating columns 【发布时间】:2015-04-25 23:41:30 【问题描述】:

我在做一个游戏,玩家一个一个地移动。我有以下表格:

╔═════════╗
║ players ║
╠═════════╣
║ id      ║
║ name    ║
╚═════════╝
╔════════════╗
║   games    ║
╠════════════╣
║ id         ║
║ started_at ║
╚════════════╝
╔═════════════╗
║ game_player ║
╠═════════════╣
║ id          ║
║ game_id     ║
║ player_id   ║
║ turn        ║
╚═════════════╝

现在,我想添加moves 表来跟踪游戏的历史。我不确定哪种方式更好:

1) 像这样将moves 与数据透视表game_player 连接起来:

╔════════════════╗
║     moves      ║
╠════════════════╣
║ id             ║
║ game_player_id ║
║ made_at        ║
╚════════════════╝

2) 像这样复制 game_idplayer_id 对:

╔═══════════╗
║   moves   ║
╠═══════════╣
║ id        ║
║ game_id   ║
║ player_id ║
║ made_at   ║
╚═══════════╝

第一个解决方案使我的数据更简洁,如果我使用外键,则无法放置不存在的游戏玩家对。

第二种解决方案使用 ORM 更容易处理。

这个问题应该如何解决?有什么方法可以轻松地使用 ORM 的第一个想法,也许是通过为游戏玩家对创建另一个实体,例如 Participation?你们会怎么做呢?

【问题讨论】:

两种方案都没有太多的关系完整性。请确认:这是一个两人(不是多人)游戏,玩家之间的动作交替。 @PerformanceDBA 这是多人游戏,1 人最多 4 人,但我不想限制为 4 人,因为我将来可能会有新的想法。 请查看答案并发表评论。 【参考方案1】:

初始响应

您的文件没有唯一性或完整性。据我了解,您需要一个具有关系完整性、功能和速度的关系数据库。

这是一个数据模型,作为讨论点。显然它并不完整,因为需要提出和关闭许多细节。但是,使用这种 SO 媒体,为您提供一些东西比来回问答要快。

初稿Game Data Model

请评论/讨论。

如果您不习惯符号,请注意,每一个小勾号、缺口和标记,实线与虚线,方角与圆角,都意味着非常具体的东西。参考IDEF1X Notation

回复评论

这个目标似乎太复杂了

哪个目标?

如果您的目标是关系数据库(作为您对该项目的任何其他目标的一部分),那么这就是最低的“复杂性”,即生成具有关系完整性的关系数据库所需的配置。所以你有责任爬上这条学习曲线。

否则,请从您的问题中删除databaserelational-database 标签。

我对数据库完整性的第一个想法是什么?

这不是违反完整性,而是缺乏完整性,即关系数据库中正常、普通、预期的那种。显然,您一直在阅读声称是关于“关系数据库”的书籍,这些书籍是由显然对关系数据库一无所知的人撰写的,并且您已经实施了他们的建议,或者您看到其他人所做的事情。

您没有关系模型所要求的行唯一性。例如。允许重复的 Player.names。例如,游戏没有上下文。

每个文件中都有ID 字段。这使记录 ID(在 RFS 中)具有唯一性,但没有行唯一性。请仔细阅读this Answer

例如。在您的 (1) 和 (2) 中,您允许玩家的移动不受他们正在玩的游戏的限制。任何现有的 player_id 和 game_id 都是允许的。

以上只是您遇到的完整性错误类型的一个示例,我没有全部列出。

我建议的模型修复了所有的完整性错误,我没有列举我修复的所有错误,我只是给了你一个有效的数据库。

为你提供一些东西比来回问答要快

例如:

独立存在的游戏的概念是不合理的。游戏仅存在于开始游戏的玩家的上下文中。所以我已经实现了。这改进了标识符,游戏现在更具上下文。

同样,没有游戏或没有参与该特定游戏的玩家存在的移动的概念是不合理的。你有那个。该模型解决了这个问题。

首先我有响应者加入游戏,由一个玩家开始。他们的总和就是该特定游戏的玩家。

接下来,我的动作受限于每个特定游戏。

接下来,我的动作被限制在每个特定游戏中的每个特定玩家。

接下来,为了正确实现它,我使用了一个基本的关系型 Basetype::Subtype 结构。这区分了initialating_player 和responding_players。它还允许我将相关约束应用于正确的表。 is_initiator 列区分基本类型。

如果您想了解有关子类型的更多信息,请研究this document

除了一个ID 之外的所有列都自然而然地消失了,没有试图摆脱它们。 player_id 剩下的一个是有效的,只是因为 player.name 可能太宽了。如果player.name 不是他们的真实姓名,如果是user_name(例如CHAR(12)),那么将player_id改为user_name,整个结构会更好。请指教,我会改进模型。

现在我们有了关系数据库的基础。我确实将其标记为初稿,我预计会出现问题,也许还有一些细微的变化。我没想到会涵盖记录归档系统和关系数据库之间的巨大差距。随意提问,我可能会建议为需要详细答案的人打开一个新问题。

【讨论】:

目标似乎太复杂了。 @Robo Robok。我在答案中做出了回应。 我对数据库完整性的第一个想法是什么? @Robo Robok。我在答案中做出了回应。 你错了In both your (1) and (2), you allow moves by players that are not constrained to the game that they are playing。在我的第一个想法中,我不允许任何游戏/用户对,只允许那些真正在玩的人。至于行唯一性,我看不出它与主题有什么关系。你怎么知道我的名字是否是唯一索引?他们实际上是,但这对我的问题无关紧要。

以上是关于加入数据透视表与复制列的主要内容,如果未能解决你的问题,请参考以下文章

可以将数据透视表与 laravel 5.5 中的另一个数据透视表相关联吗?

如何使用 Laravel 将两个表与数据透视表连接起来?

在 Eloquent 中将数据透视表与多个表连接起来

Laravel多态多对多关系数据透视表与另一个模型的关系

是否可以在 Laravel 中获取数据透视表与另一个表的关系?

Excle数据透视二维数据如何创建数据透视表