【问题标题】:Convert One to Many to One to One Relationship MySQL将一对多对一关系转换为 MySQL
【发布时间】:2015-06-02 17:41:15
【问题描述】:

我有两个 MySQL 表,我们可以分别调用 FooBar

两个表都有一个名为PrizeGroupId 的列。目标是在这些列之间创建一对一的关系,我创建了存储过程来添加/编辑Foo,通过Bar 中的一对一关系更新相应的行。

问题在于数据并非总是以这种方式结构化,我需要编写一个脚本将数据从之前的状态(我将要描述)转换为一对一基于PrizeGroupId 的关系。

以前,Foo 中的多行可能具有相同的 PrizeGroupId,因此基于 PrizeGroupIdBarFoo 中的条目之间存在一对多关系。我需要编写的脚本必须将这种性质的每个一对多实例分解为FooBar 之间的许多(几乎相同)一对一关系。

原则上,我想:

  1. 遍历Foo
  2. 查看当前行的PrizeGroupIdFoo 中是否不唯一。
  3. 为其分配一个唯一值(可能是当前项目的主键)
  4. 使用新的PrizeGroupIdBar 中添加一行。将旧行的所有其他数据复制到新行中,使其“几乎相同”。
  5. 说到底,从Bar 中删除旧的一对多行。

我了解这个问题,以及我如何在编程语言的伪代码中做到这一点,但是我仍在学习 MySQL,不知道如何解决这种性质的问题。

如果您可以通过 MySQL 代码为我提供帮助和/或我可以采取/阅读哪些步骤来解决这个问题,或者至少指出与此相关的阅读/SO 问题尽管我很难自己找到特定的资源,但这种问题将不胜感激。

【问题讨论】:

    标签: mysql one-to-many one-to-one


    【解决方案1】:

    你所要求的并不难。你的一些想法妨碍了你。首先,几乎从不迭代 SQL。 SQL 不是那种语言。 SQL 中的一切都是通过一组东西来完成的。

    您的方法可以是:

    1. 确定 PrizeGroupId 已经是唯一的行集并将它们移动到表的新副本。

    要创建表,可以使用“create table foo2 like foo;”。很有用。

    要识别 PrizeGroupId 已经是唯一的行,请使用以下内容:

    create table test_30602977 (id int primary key, other int);
    insert into test_30602977 values (1, 1), (2, 2), (3, 2);
    select other, count(*) as count from test_30602977 group by other having count = 1;
    
    1. 原始表中剩下的行没有唯一的 PrizeGroupId。更改 PrizeGroupId 值,使它们是唯一的。

    2. 合并这两个集合以重建具有原始行且 PrizeGroupId 唯一的表。

    这很困难的一个原因是,如果您使用一对一连接创建了表,那么您将使用 pk 来连接这些表。 pk 已经是独一无二的,所以为什么要使用其他东西。一旦您将表格分开并且 PrizeGroupId 是唯一的,您可能需要考虑将 foo 的 pk 设置为 bar 的 pk,然后删除 PrizeGroupId 列。

    【讨论】:

    • 我不明白“识别 PrizeGroupId 所在的行”这行,你的意思是要在那里输入更多吗?
    【解决方案2】:

    Bar 表需要为 Foo 中的每条记录包含一条记录,并且 Foo 中的 PrizeGroupId 字段必须是唯一的。由于 Foo.Id 已经是唯一的,因此将其用作外键是有意义的。

    运行SELECT Foo.id, Bar.* FROM Foo INNER JOIN Bar USING (PrizeGroupId) 之类的查询将为 Foo 中的每条记录提供一条记录,以及来自 Bar 中相应记录的数据。因此,如果我们将 Bar 中的数据替换为此查询返回的数据,然后将 Foo.Id 用于 PrizeGroupId,我们将实现所需的内容。

    1. 创建一个与 Bar 结构相同的临时表 - 类似于 CREATE TABLE Bar_copy LIKE Bar

    2. 用 Foo 中的每条记录填充临时表,连接到 Bar 中的相应记录 - 您需要列出 Bar 中的所有列,例如 - INSERT INTO Bar_copy (id, field1, field2, field3) SELECT f.id, b.field1, b.field2, b.field3 FROM Foo AS f INNER JOIN Bar AS b USING (PrizeGroupId)

    3. 从 Foo 中清除现有的 PrizeGroupID 字段 - UPDATE Foo SET PrizeGroupId = NULL

    4. 清空现有的 Bar 表并用临时表中的记录重新填充它 - INSERT INTO Bar (id, field1, field2, field3) SELECT id, field1, field2, field3 FROM Bar_copy

    5. 更新 Foo 中的外键值 - UPDATE Foo SET PrizeGroupId = id

    当然,先备份!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 2012-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-27
      相关资源
      最近更新 更多