您如何使一对一或其他关系正常化?
Posted
技术标签:
【中文标题】您如何使一对一或其他关系正常化?【英文标题】:How do you normalize one-to-one-or-the-other relationships? 【发布时间】:2011-01-30 19:39:26 【问题描述】:我正在存储有关棒球统计数据的数据,并希望使用三个表来存储:players、battingStats 和 pitchingStats。就问题而言,每个球员都有击球数据或投球数据,但不能同时拥有。
如何在 3NF 中规范这种关系?
【问题讨论】:
您已经有了解决方案。使用您的问题中描述的三个表,以及下面 Steven A. Lowe 描述的键。您可能在内部您的统计数据表中存在进一步的规范化问题,但您已经正确地建模了球员和统计数据之间的关系。 @Steven,我同意投手击球(在 NL 和联盟比赛中),但这是一个梦幻棒球选秀工具,投手的击球数据不算数。 【参考方案1】:PlayerId 在 BattingStats 和 PitchingStats 表中都是外键
[记得在统计表中加入一些时间维度(季节、年份等)]
顺便说一句,这是一个错误的假设:据我所知,投手也可以击球!
【讨论】:
【参考方案2】:您真的要求不要使用超过 3 个表吗? Normalization 通常意味着将一个非规范化模型分解为许多规范化关系。
如果您可以拥有 3 个以上的表,您可能需要考虑以下(3NF):
Players: ([player_id], name, date_of_birth, ...)
Batters: ([batter_id], player_id)
Pitchers: ([pitcher_id], player_id)
Batting_Stats: ([batter_id, time_dimension], stat_1, stat_2, ...)
Pitching_Stats: ([pitcher_id, time_dimension], stat_1, stat_2, ...)
[]
中的属性定义主键,但如果愿意,可以使用surrogate key。 Batters and Pitches 中的player_id
属性应该有一个unique constraint,它也应该是一个foreign key 与Players 关系。 Batting_Stats 和 Pitching_Stats 也应该分别具有 Batters 和 Pitching 的外键。
但请注意,上述内容并不强制规定球员只能是击球手或投手。
更新:
我知道的一种强制球员只是击球手或投手的方法是通过这个模型:
Players: ([player_id], name, date_of_birth, ...)
Roles: ([role_id, role_type], player_id)
Batting_Stats: ([role_id, role_type, time_dimension], stat_1, stat_2, ...)
Pitching_Stats: ([role_id, role_type, time_dimension], stat_1, stat_2, ...)
role_type
应该定义投手或击球手。 Batting_Stats 和 Pitching_Stats 应该有一个使用(role_id, role_type)
的角色的复合外键。对角色中player_id
的唯一约束将确保玩家只能拥有一个角色,并且只能拥有一个角色。最后添加check constraints,这样Batting_Stats.role_type = 'Batter'
和Pitching_Stats.role_type = 'Pitcher'
。这些检查约束保证 Batting_Stats 总是描述击球手,并注意投手。 Pitching_Stats 也是如此。
【讨论】:
对我来说,插入 Batters 和 Pitchers 表如何改进数据模型或使其更正常并不是很明显。如果 player_id 直接在 Batting_Stats 和 Pitching_Stats 表中使用,这些表似乎只会重复出现的数据。 @Larry:这些表格定义了“球员池”中的击球手组和投手组。那是新信息。那么击球数据只能指“击球组”中的球员,投球也是如此。 但是通过检查 Batting_Stats 和 Pitching_Stats 中的 player_id 列可以获得完全相同的信息。但是,我确实看到了由您的设计处理的另一种情况——在根本没有任何统计数据的情况下定义玩家的角色。如果需要,那么额外的表将满足该需求(就像 Players 中额外的 role_type 列一样)。 有时这种角色/类型安排是必要的,但我在这里看不到。预先,您已经知道所有角色,因此没有理由提供添加其他角色的能力。此外,通过这样做,您可以为角色表中的各个行(“投手”与“击球手”)赋予意义,作为执行数据规则和构建适当查询的一种手段。同样,这有时是必要的,但除非绝对需要,否则应避免这样做。【参考方案3】:我知道如何从实际的角度实现这一点(我会在不相交的表上创建一个 UNIONed 视图,并在玩家 ID 上放置一个唯一索引 - 因此,它们只能出现在一个表中)。
或者在球员表中,记录他们拥有什么类型的统计数据,然后将其包含在统计数据表中的 FK 关系中。
但其中任何一个都可能比您想要的更接近金属。
【讨论】:
以上是关于您如何使一对一或其他关系正常化?的主要内容,如果未能解决你的问题,请参考以下文章