SQL:多对多对多对多......这有效吗?

时间:2012-04-24 21:38:57

标签: mysql sql

提前感谢您的意见。

我有3个对象:

  • 学校
  • 教练

具有以下关系:

  • 学校可以有多个夏令营。
  • 学校可以有多名教练。
  • 营地可以有多个学校。
  • 一个营地可以有多个教练。
  • 教练可以有多个学校。
  • 教练可以有多个训练营。

很多人,School_Camp,显然将学校与营地联系起来,并为Date添加一个额外的领域,以确定营地的年份。但是一个阵营可以有多个教练。

:: School_Camp ::

  • 学校ID
  • Camp_id
  • 日期

对我来说,设置另一个可以链接到School_Camp和Coach表的School_Camp_Coach会不会更好?

:: School_Camp_Coach ::

  • School_Camp_id
  • Coach_id

如果这是更有效的方法...我应该给School_Camp一个独立的id列,可以快速引用而不是使用这三个字段作为标识符吗?

:: School_Camp ::

  • ID *
  • 学校ID
  • Camp_id
  • 日期

只有一个多对多的桌子,School_Camp_Coach,有3个外键是否更好?

:: School_Camp_Coach ::

  • 学校ID
  • Camp_id
  • Coach_id
  • 日期

我预见到的唯一问题是,您将拥有多个外键条目,但具有不同的日期。

再次感谢。

3 个答案:

答案 0 :(得分:2)

这不是效率问题,而是正确性问题:您提出的两个选项不会建模表中记录之间的相同关系。

数据库中的每条记录都意味着什么。如果联结表中记录的含义是“X在学校Z的Y营地训练”,那么你应该选择2;如果你想要模仿“X训练营Y”的意思,独立于“X训练Z学校”并独立于“Z学校阵营Y”,那么你应该选择1。

在这两种情况下,您都应该为联结记录提供独立的主键,而不是依赖于ID的三向组合:当您实现对联结表应用更正的代码时,它将简化您的生活。

答案 1 :(得分:1)

请参阅@Ted Hopp的评论。

鉴于数据(学校营地每分钟不会发生多次),我认为更新时间不如检索时间优先。如果这是真的,我会选择你的最后一个选项,3个外键。

这是star schema的一个例子。

答案 2 :(得分:0)

我的Coach实体看起来像是一个应该具有我通常称之为basket的实体,它可以与多对多关系中的其他实体链接。这是我的意思:

# The coach model
CREATE TABLE coach(
    id INT NOT NULL AUTO_INCREMENT,
    PRIMARY KEY(id),
    name VARCHAR(20),
    capacity INT
) ENGINE=InnoDB;

# The coach data - who is using the coaches
CREATE TABLE coach_basket(
    coach_id INT,
    FOREIGN KEY(coach_id) REFERENCES coach(id),
    entity_id INT, /* the school or camp id */
    entity_type ENUM("School","Camp"),
    fromdate DATETIME,
    todate DATETIME
) ENGINE=InnoDB;

所以现在你可以跟踪所有的教练用法,只需输入entity_id(学校或训练营ID),以及他们每次使用教练时使用它们的日期和时间。

您需要一个类似的表格来存储哪些学校和营地相连,它可能如下所示:

# Store school-camp connections
CREATE TABLE connections(
    school_id INT,
    FOREIGN KEY(school_id) REFERENCES school(id),
    camp_id INT,
    FOREIGN KEY(camp_id) REFERENCES camp(id)
) ENGINE=InnoDB;

非常简单,只需要上学和露营身份证,所以如果你查询一个school_id,你会得到许多与学校有联系的营地,反之亦然。

剩下的就是你的schoolcamp表,它们是模型(如顶部的coach表)。