【问题标题】:Handling multiple many-to-many relationships on same table?处理同一张表上的多个多对多关系?
【发布时间】:2019-02-05 10:38:17
【问题描述】:

我是一名偶然的 DBA。我使用的大多数数据模型都可以表示为简单的一对多关系,在这里或那里使用奇数连接表来模拟偶尔的多对多关系。我遇到了一种对我来说很陌生的情况,我不确定建模它的正确方法。

我的应用程序规定可以通过几种不同的方式修改特定属性,这些方式需要单独指定。考虑一个来自 D&D 的示例,其中怪物可以对各种伤害类型(例如“抵抗酸、火和闪电,易受寒冷)具有抵抗力、免疫或脆弱性

在这个例子中,我的第一个想法是为怪物、修改类型和伤害类型以及它们之间的连接表构建单独的表 - 如下所示。

CREATE TABLE monsters (
    id char(32) NOT NULL,
    monster_name varchar(100) NOT NULL,
    PRIMARY KEY (id)
)

CREATE TABLE dmgModTypes (
    id char(32) NOT NULL,
    dmg_modifier varchar(20) NOT NULL,
    PRIMARY KEY (id)
)

CREATE TABLE dmgTypes (
    id char(32) NOT NULL,
    dmg_type varchar(25) NOT NULL,
    PRIMARY KEY (id)
)

CREATE TABLE monster_dmg_mod (
    id char(32) NOT NULL,
    monster_id char(32) NOT NULL,
    dmgModType_id char(32) NOT NULL,
    dmgType_id char(32) NOT NULL,
    PRIMARY KEY (id),
    KEY monster_dmg_mod_monster_id_fk_monsters_id (monster_id),
    KEY monster_dmg_mod_dmgModType_id_fk_dmgModTypes_id (dmgModType_id),
    KEY monster_dmg_mod_dmgType_id_fk_dmgTypes_id (dmgType_id),
    CONSTRAINT monster_dmg_mod_monster_id_fk_monsters_id
        FOREIGN KEY (monster_id)
        REFERENCES monsters (id),
    CONSTRAINT monster_dmg_mod_dmgModType_id_fk_dmgModTypes_id
        FOREIGN KEY (dmgModType_id)
        REFERENCES dmgModTypes (id),
    CONSTRAINT monster_dmg_mod_dmgType_id_fk_dmgTypes_id
        FOREIGN KEY (dmgType_id)
        REFERENCES dmgTypes (id)
)

这个功能,但感觉...不好。 我想我也可以为每种修改类型制作单独的表格...

monster--|
         |-Resistance
dmg_type-|

monster--|
         |-Immunity
dmg_type-|

monster--|
         |-Vulnerability
dmg_type-|

...但这也不太对劲。是否有对此类行为建模的标准?

抱歉,如果这是重复的 - 我正在学习如何描述这种事情的具体术语。

【问题讨论】:

  • 就像很多事情一样......这取决于。这种设计的优点是新类型将更容易添加。缺点是你的查询和维护会比较复杂。从来没有“完美”的设计,在现实中,我们常常发现自己偏离了完美的理论来创造更实用的东西。这些数据也并非存在于真空中。一个应用程序将读取和解释,所以我可能只是在表格中使用可以是正数或负数的电阻因子来制作这些列,以便数学计算出正数是电阻,负数是易受攻击的
  • 听起来“过度标准化”。也许 Monster 表只包含一个用于抵抗等的列,并且在该列中是一个字符串,而不是指向该字符串的 id。
  • @RickJames,你可能是对的,尽管实际的数据库结构(D&D 只是关系功能的一个例子)很可能会在未来添加或删除修饰符类型,我不知道除非我在这件事上别无选择,否则不要想在表中添加/删除列。不过,值得考虑。谢谢。
  • 另一种模式模式是 EAV,但它有很多问题。

标签: mysql database-design


【解决方案1】:

@Jeremy 在原始帖子的 cmets 中的输入非常有启发性。在这种情况下,似乎没有真正的“正确”方法来处理这种情况,答案在很大程度上取决于上下文。在我的特定用例中,我最终为关系的每个维度创建了一个表,并使用类似连接的表来描述关系本身:

monster------|
             |
dmg_type-----|--Junction (cols. for monster, dmg_mod_type, dmg_type)
             |
dmg_mod_type-|

在我的特定业务案例中,我们很可能会定期添加或删除修饰符(实际上是“添加 dmg_mod_types”),这使得根据需要添加和删除变得非常容易。如果这些修饰符及其相关值更静态,则将它们分成单独的表可能更有意义,或者实际上在“怪物”表中添加一列来表示修饰符。

感谢您的意见 - 我将此问题标记为已关闭。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 2020-09-09
    • 2014-07-11
    • 2015-11-12
    • 2021-07-11
    相关资源
    最近更新 更多