【问题标题】:Database design: One to one relationship from a single table?数据库设计:来自单个表的一对一关系?
【发布时间】:2018-01-12 22:53:14
【问题描述】:

对于一个学校科目,我必须创建一个具有不同类型关系的小型应用程序:一对一、一对多、多对多。

例如,如果来自同一个表“用户”的 2 个用户 ID 之间的关系状态(已婚/已婚)仍然是一对一的关系?

例如:

表 1:“用户”

user_id (PK) |用户名 |密码 |注册日期

表 2:“关系”

user_one_id (FK) | user_two_id (FK) |状态

这是一对一数据库的正确示例,还是它本身必须是 2 个表与连接它们的外部表之间的连接?

【问题讨论】:

  • 尽你所能。我一直在这样做,我从未见过适合一对一关系的情况。但是,您的情况似乎是学术性的,这意味着它不一定代表现实生活。对于您在问题中的示例,问问自己您的数据模型如何处理关系结束。

标签: mysql sql database database-design


【解决方案1】:

如果“连接它们的外部表”是指第三个表,那么不,没有必要。

不过,您的关系表可能需要做一些工作。您不希望有两个带有用户 ID 的字段。这会让你以后头疼。我建议像这样设置这些表:

USER

user_id (pk)
username
password        --Potential security problems, but for academic purposes, sure.
date_registered
family_unit_id


RELATIONSHIP

family_unit_id (fk)
user_id (fk)
spouse_type --(e.g. husband, wife, etc.)

现在您可以通过以下方式建立多对多关系:

SELECT r.family_unit_id, r.user_id, u.username
FROM RELATION r LEFT JOIN USER u ON r.user_id = u.user_id

您的一对一关系将是表之间的同一记录所独有的。在您描述的情况下,与 user_id (妻子)相关的 user_id (丈夫)不是一对一的关系。根据您提供的内容,您可以通过连接数据子集来建立一对一的关系,例如这个示例。

SELECT r1.family_unit_id, r1.username as HusbandName, r2.username as WifeName
FROM (SELECT * FROM RELATION WHERE spouse_type = 'Husband') r1
LEFT JOIN (SELECT * FROM RELATION WHERE spouse_type = 'Wife') r2
     ON r2.family_unit_id = r1.family_unit_id

上面的查询基本上得到了两个表,它们的唯一主键是family_unit_ids,用户ID 与丈夫或妻子相关联。然后,您将它们连接在一起。因为我们假设在此示例中已婚家庭单元中的配偶永远不会超过两个,所以这将是一对一的关系。

如果您想建立一对多关系,您可以从 USER 表中选择所有内容,然后加入 RELATIONSHIP 表以显示合作伙伴是谁:

SELECT u.username, r.user_id
FROM USER u LEFT JOIN RELATIONSHIP r ON r.family_unit_id = u.family_unit_id

当然,这将是一个微不足道的结果,因为您会有记录说约翰与约翰和玛丽有关系。但它说明了这一点。通常,通过将更多表添加到此组合中,您将获得对一对多关系更有用的结果。

【讨论】:

  • 感谢您的评论。我有点困惑。我想知道除了列的命名(user_one_id、user_two_id 和 user_id、family_unit_id)之外,我的表(关系)和你的表之间有什么区别。
  • 将 user_one_id 和 user_two_id 组合成一个字段:user_id。或者,您可以指定家庭职位:hub_user_id、wife_user_id。指定一个/两个的问题在于,任何一个人都可能符合条件,因此以后搜索和加入将更加困难。
  • 丈夫/妻子领域硬编码的缺点是当您遇到非传统家庭时。丈夫/丈夫,妻子/妻子等。所以,这取决于您对数据库的目标是什么以及您要接受什么样的数据。
  • 或者,如果永远只有一个配偶,您可以删除关系表并将其替换为用户表中的另一个字段:save_user_id
  • 非常感谢您的帮助。我终于想出了一个数据库设计。
【解决方案2】:

简短的回答不是真的。

当您在两个表的主键之间建立关系时,您会得到一对一的关系。

接受你的想法:假设我们有很多用户,但我们在这样的表格中跟踪他们的登录信息:

CREATE TABLE users (
    user_id int NOT NULL PRIMARY KEY,
    username varchar,
    password varchar);

还有一张这样的表:

CREATE TABLE user_personal(
    user_id int NOT NULL PRIMARY KEY,
    age int,
    firstname varchar,
    lastname varchar)

创建两个表后,很容易看到每个表中都有一个列具有相同的数据类型 (user_id),用作该表的主键。

如果您使用 user_id 作为键在两个表之间建立关系,那么您已经建立了一对一的关系,因为 user_id 在任一表中只能出现一次。

这可能看起来有点奇怪,因为您可能会问为什么要这样分离数据。为什么要区分包含在一个表中而不包含在另一个表中的数据字段?一种简单的解决方案是数据隔离。假设我们修改了第二个表格以显示这一点:

CREATE TABLE user_personal(
    user_id int NOT NULL PRIMARY KEY,
    age int,
    firstname varchar(255),
    lastname varchar(255),
    home_address varchar(255),
    social_security_number int)

我们可能希望将某些数据的访问权限授予某些人,而不是其他人。如果您有您的用户关系表,那么向某些人展示人们彼此之间的家庭/友谊关系可能会很好,但您不希望泄露他们的社会安全号码和家庭住址。您可能会分离数据的另一个重要原因是,如果您的表中包含大量数据(想想数百列),并且在任何特定时间只有一些数据得到更新。如果您有数百万条要更新的记录,但只有某些列一起更新,而其他列保持相当静态,您可以将该表分成两个具有一对一关系的表,以防止数据库性能在更新进程。

【讨论】:

  • 谢谢!这是非常有用的信息。明天我会进一步研究它,并将在我的应用程序中实现它。
猜你喜欢
  • 2015-08-05
  • 2014-11-06
  • 2018-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-17
相关资源
最近更新 更多