1

我在编写多:多关系时遇到了一些困难,如下图所示:

在此处输入图像描述

我想要设置这些表和关系,以便:

  • 一个父母可以有多个孩子(这里的孩子是“玩家”),一个孩子可以有一个或多个父母(最多两个)。
  • “家庭”可以由一个或多个父母(最多两个)以及一个或多个孩子(无限)组成。

我不知道如何容纳与“孩子”姓氏不同的父母,反之亦然。我还没有被告知这是否会成为一个问题,但我认为这是值得考虑的事情。Parent 和 Player 类都从 person 超类继承字段(如名字和姓氏、地址、年龄、出生日期等)。

当我意识到我不确定如何插入一个或多个父母与他们是父母(或照顾者)的一个或多个孩子时,我正要测试一些输入到家庭表中。我以为我在理论上已经解决了这个问题,但在测试后我意识到它不起作用,我花了 90 多分钟为一些想法画草图,但我真的迷路了。

==================================================== =================================

更新:27-04-2012 @ 22:19PM NZST

我应该给出我正在寻找的结果的可视化表示 - 在查询包含这些表的数据库时。这是视觉表示:

+-------------------+-----------------+---------------------+
| ParentsFirstName  | ParentsLastName | ChildrenInFamily    |
+-------------------+-----------------+---------------------+
| Gregory           | Peck            | Michael             |
| Laura             | Peck            | Michael             |
| Martha            | Petersen        | Matt, Christopher   |
| Chris             | Michaels        | Richard, Shaun      |
| Nadine            | Michaels        | Richard, Shaun      |
| Barry             | Dackers         | Harry               |
| Kevin             | Mitchell        | Daniel              |
| Rebecca           | Mitchell        | Daniel              |
+-------------------+-----------------+---------------------+

“孩子”在名为“玩家”的表中,父母在名为“父母”的表中。这篇文章中的 MySQL 代码代表了关于这个特定问题的表(你应该注意到我使用 Person 类作为超类,而父/子表作为子类)。通过使用外键引用其他一些表(“schoolID”字段来自名为“School”的表,该表具有“schoolName”字段)。

我不确定我是否已经为我想要实现的目标构建了正确的表,但是在做一些研究时,我发现了一个名为GROUP_CONCAT的函数,它至少让我想到了查询可能是什么样子——对于这个特定的问题。

容纳不同姓氏的父母,以及与父母不同姓氏的孩子,是我什至无法解决的另一个重大挑战(我想这是寄养家庭也是如此)。因此,对于上述可视化,我假设非单亲父母已婚并拥有相同的姓氏,并且孩子都与已婚父母拥有相同的姓氏。

==================================================== =================================

这是我尝试创建的一些代码,用于创建试图处理这部分的数据库部分(注意:“玩家”是父母的“孩子”):

DROP TABLE IF EXISTS `person` ;
CREATE TABLE `person` (
  `personID` INT(5) NOT NULL AUTO_INCREMENT ,
  `firstName` VARCHAR(50) NOT NULL ,
  `lastName` VARCHAR(50) NOT NULL ,
  `dateOfBirth` DATE NOT NULL ,
  `personType` CHAR(6) NOT NULL, 
  `photo` BLOB NULL DEFAULT NULL ,
  PRIMARY KEY (`personID`))
ENGINE = InnoDB;
SHOW WARNINGS;

DROP TABLE IF EXISTS `parent` ;
CREATE TABLE `parent` (
  `parentID` INT(5) NOT NULL,
  FOREIGN KEY (`parentID`) REFERENCES `person` (`personID`)
  ON DELETE CASCADE 
  ON UPDATE CASCADE)
ENGINE = InnoDB;
SHOW WARNINGS;

DROP TABLE IF EXISTS `player` ;
CREATE TABLE `player` (
  `playerID` INT(5) NOT NULL, 
  `schoolID` INT(5) NOT NULL,
    FOREIGN KEY (`playerID`) 
    REFERENCES `person` (`personID`)
    ON DELETE CASCADE 
    ON UPDATE CASCADE, 
    FOREIGN KEY (`schoolID`)
    REFERENCES `school` (`schoolID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;
SHOW WARNINGS;

DROP TABLE IF EXISTS `family` ;
CREATE TABLE `family` (
  `parentID` INT(5) NOT NULL ,
  `playerID` INT(5) NOT NULL ,
  PRIMARY KEY (`parentID`, `playerID`), 
    FOREIGN KEY (`playerID` )
    REFERENCES `player` (`playerID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    FOREIGN KEY (`parentID`)
    REFERENCES `parent` (`parentID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;
SHOW WARNINGS;

如果有人可以通过提供一些指导,甚至是一些带有解释的通用示例来帮助我解决这个问题,那就太好了。我认为这是一个多对多的关系,我不能完全放弃,因为父母可以有一个或多个孩子,一个孩子可以有一个或多个父母(在这种情况下,一个家庭不会是没有孩子的家庭) )。

提前谢谢了!!!

4

7 回答 7

2

一个孩子不能有超过 2 个父母,他们都有特定的角色(母亲与父亲),并且可能存在一个或两个父母未知的情况。

所以这不是真正的“多对多”关系,它实际上是“多对零或一或二”,可以自然地表示为(两者都可以为MotherIDNULL FatherID):

在此处输入图像描述

如果您LastName同时输入Parentand Player(或在您的情况下输入一个共同的超类),这自然也涵盖了父母与孩子姓氏不同的情况。

然后,您可以像这样轻松获得“每个父母的孩子”(SQL Fiddle)......

SELECT
    ParentID,
    Parent.FirstName ParentFirstName,
    Parent.LastName ParentLastName,
    PlayerID,
    Player.FirstName PlayerFirstName,
    Player.LastName PlayerLastName
FROM
    Parent
    LEFT JOIN Player
        ON Parent.ParentID = Player.MotherID
        OR Parent.ParentID = Player.FatherID
ORDER BY ParentId

...如果您愿意,可以在您的应用程序代码中旋转数据。


上述模型允许Parent的性别与其母亲/父亲角色不匹配。如果你想防止这种情况,你可以过火并做这样的事情......

在此处输入图像描述

...但我宁愿不要复杂化并坚持使用第一个模型并在应用程序级别强制执行它。

于 2012-04-27T11:50:08.507 回答
2

我会质疑家庭实体的使用。一个孩子可以通过父母的离婚和随后的再婚成为两个家庭的成员——你会如何建模?一个孩子可能没有四个人有效地“代替父母”行动吗?

于 2012-04-27T13:33:58.797 回答
1

您只需要一个包含两个字段的连接表:孩子、照顾者。这基本上就是你的“家庭”表的内容 - 我不明白你的“父母”表的目的。“family”中的两个值都是“person”的外键(即,使“player”成为比图表中更通用的表。)

这样一来,任何孩子都可以拥有任意数量的看护人。任何照顾者都可以与任何数量的孩子联系在一起。不正当和美妙的家庭安排的所有可能组合都被容纳了。

于 2012-04-27T23:05:30.353 回答
0

实现多对多关系的 Family 表通常是在用户输入 Parent/Player(s) 数据之后创建的。UI 通常被描述为主窗体/子窗体组合,其中父窗体从主窗体中输入/选择,并且与父窗体关联的一个或多个玩家在子窗体中输入/显示;通常是某种网格。

于 2012-04-27T06:19:33.273 回答
0

我不确定这本身是否是一个“答案”,但这是我尝试调整我的 MySQL 代码以适应Branko Dimitrijevic的答案为我提供的内容。这是我为相关表调整的 MySQL 代码:

DROP TABLE IF EXISTS `person` ;
CREATE TABLE `person` (
  `personID` INT(5) NOT NULL AUTO_INCREMENT ,
  `firstName` VARCHAR(50) NOT NULL ,
  `lastName` VARCHAR(50) NOT NULL ,
  `dateOfBirth` DATE NOT NULL ,
  `personType` CHAR(6) NOT NULL, 
  `photo` BLOB NULL DEFAULT NULL ,
  PRIMARY KEY (`personID`))
ENGINE = InnoDB;
SHOW WARNINGS;

DROP TABLE IF EXISTS `parent` ;
CREATE TABLE `parent` (
  `parentID` INT(5) NOT NULL,
  PRIMARY KEY (`parentID`), 
  FOREIGN KEY (`parentID`) REFERENCES `person` (`personID`) 
  ON DELETE CASCADE 
  ON UPDATE CASCADE)
ENGINE = InnoDB;
SHOW WARNINGS;

DROP TABLE IF EXISTS `player` ;
CREATE TABLE Player (
    `playerID` INT(5) NOT NULL,
    `motherID` INT(5),
    `fatherID` INT(5),
    `schoolID` INT(5),
    PRIMARY KEY (`playerID`), 
    FOREIGN KEY (`playerID`) REFERENCES `person` (`personID`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE,
    FOREIGN KEY (`motherID`) REFERENCES `parent` (`parentID`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE,
    FOREIGN KEY (`fatherID`) REFERENCES `parent` (`parentID`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE, 
    FOREIGN KEY (`schoolID`) REFERENCES `school` (`schoolID`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE)
ENGINE = InnoDB;
SHOW WARNINGS;

这是具有这些表的逻辑模型的一部分:

在此处输入图像描述

如果布兰科或其他任何人可以用布兰科的回答来验证我的尝试,那就太好了。您还会注意到,对于图像,我使用 MySQL Workbench 作为模型。

以下内容超出了这个特定问题的范围,但如果有人能帮助解决这个问题,那就太好了:

我被要求不要使用反向或正向工程将 sql 代码转换为模型模式等,但这使我能够验证我在 Visio 中构建的模型的正确性。但是,我不能完全让 Visio 模型看起来像 Workbench 模型 - 这是我试图在上面建模的表的 Visio 版本:

在此处输入图像描述

正如您在 Visio 版本中看到的那样,“fatherID”和“motherID”列未指示为外键,这是我想要的(在 Workbench 版本中进行了说明)。如果有人可以帮助我让我的 Visio 模型看起来与 Workbench 版本相同,那就太好了。

于 2012-04-28T01:42:19.557 回答
0

我不确定为什么一个人会有多个地址——但我想他们可以。但是,如果我正在处理多个地址,那么我会将地址推送到另一个表中并有一个 person_address 加入表。这样,您就不会为居住在同一地址的每个人重复地址数据。

您的父表需要两个字段 - 一个用于父级,另一个用于播放器(正如我之前所说的,我认为如果它们都指向人,它会更好地工作)。为什么你在父母和玩家之间有两条关系线?

person|parent 关系不会是 1..1 - 1..1,因为这意味着每个人都是父母,而您的玩家可能不是。

顺便说一句——但你似乎真的很关注母亲和父亲。可能没有任何一个,也可能有多个。您不需要单独的关系来规定性别 - 这应该是 PERSON 中的数据,或者根本不存在无关紧要的数据。

于 2012-04-28T07:15:08.387 回答
0

好的,这太痛苦了。你把它复杂化了。我没有 visio,所以请尝试应对:

  • PERSON(person_id, first_name, last_name) PK: person_id
  • FAMILY(parent,player) PK:(parent,player) FK:FAMILY.parent -> PERSON.person_id, FK:player->PERSON.person_id

就是这样——简单。

您所需要的只是一张将两个不同的人匹配在一起的桌子。要找到孩子的所有看护人,您只需将人与人结合并为孩子进行过滤。

地址:

  • PERSON_ADDRESS(person_id,address_id) PK:(person_id,address_id) FK:person_id->person.person_id, FK:address_id->address.address_id
  • ADDRESS(address_id,st-num,street, city,phone) PK:address_id 其中 st-num 可能是 23B 之类的字母数字

实际上 - 我不喜欢你把电话放在地址里。不会扩展到地址中的多个电话号码。但是地址是一种干扰。您的问题似乎是关于将玩家与父母联系起来。

学校应该是它自己的桌子。将 school_id 放入 person 中,或者如果您讨厌空值,则有一个连接表 person_school ,其中只有孩子的记录

于 2012-04-28T08:08:26.367 回答