代码之家  ›  专栏  ›  技术社区  ›  Yes - that Jake.

如何使一对一或其他关系正常化?

  •  5
  • Yes - that Jake.  · 技术社区  · 16 年前

    我正在存储棒球统计数据,并且希望使用三个表来存储:players、battingStats和pitchingStats。就问题而言,每个球员都有击球数据或投球数据,但不是两者都有。

    我该如何在3NF中使这种关系正常化?

    3 回复  |  直到 16 年前
        1
  •  6
  •   Steven A. Lowe    16 年前

    PlayerId在BattingStats和PitchingStats表中都是外键

    顺便说一句,这是一个错误的假设:据我所知,投手也可以击球!

        2
  •  2
  •   Daniel Vassallo    16 年前

    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 如果愿意,可以使用。这个 player_id 击球手和投手的属性应该有 unique constraint ,它也应该是一个 foreign key 与玩家的关系。击球和投球统计数据也应该有一个外键,分别指向击球手和投手。

    但请注意,上述规定并不强制要求球员只能是击球手或投手。


    我所知道的一种方法是通过这个模型来强制一个球员只是击球手或投手:

    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 应该定义投手或击球手。击球统计数据和投球统计数据应该有一个复合外键给角色使用 (role_id, role_type) 玩家id in Roles将确保一个玩家只能有一个角色。最后添加 check constraints 以便 Batting_Stats.role_type = 'Batter' Pitching_Stats.role_type = 'Pitcher'

        3
  •  1
  •   Damien_The_Unbeliever    16 年前

    我知道如何从实际的角度来实现这一点(我会在不相交的表上创建一个UNIONed视图,并在player ID上放置一个唯一的索引-因此,它们只能出现在一个表中)。

    但这两个可能都比你想要的更接近金属。