转换一对多对一对一的关系 MySQL

Convert One to Many to One to One Relationship MySQL

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

两个表都有一个名为 PrizeGroupId 的列。目标是在这些列之间创建一对一关系,我已经为 add/edit Foo 创建了存储过程,通过 [=12] 中的一对一关系更新相应的行=].

问题在于数据并不总是以这种方式构建,我需要编写一个脚本来将数据从之前的状态(我将要描述的)转换为一对一的-基于 PrizeGroupId.

的关系

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

原则上,我想:

  1. 遍历Foo
  2. 查看当前行的 PrizeGroupId 是否在 Foo 中不是唯一的。
  3. 为其分配一个唯一值(可能是当前项目的主键)
  4. 使用新的 PrizeGroupIdBar 中添加一行。将旧行的所有其他数据复制到此新行中,使其成为 "nearly identical".
  5. 说完所有后,从 Bar 中删除旧的一对多行。

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

如果您可以通过 MySQL 代码向我提供帮助 and/or 我可以采取哪些步骤 take/read 将着手解决这个问题,或者至少向我指出与此类问题相关的 reading/SO 问题将不胜感激,尽管我自己很难找到特定的资源。

你问的并不难。你的一些想法正在妨碍你。首先,几乎从不在 SQL 中迭代。 SQL 不是那种语言。 SQL 中的所有内容都是通过一组东西完成的。

您的方法可以是:

  1. 识别 PrizeGroupId 已经唯一的行集,并将它们移动到 table 的新副本。

要创建 table,您可以使用 "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. 原始 table 中剩余的行没有唯一的 PrizeGroupId。更改 PrizeGroupId 值,使其唯一。

  2. 合并这两个集合以使用原始行和唯一的 PrizeGroupId 重建 table。

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

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

运行 像 SELECT Foo.id, Bar.* FROM Foo INNER JOIN Bar USING (PrizeGroupId) 这样的查询将为我们提供 Foo 中每条记录的单个记录,以及来自 Bar 中相应记录的数据。因此,如果我们用此查询返回的数据替换 Bar 中的数据,然后将 Foo.Id 用于 PrizeGroupId,我们将达到要求。

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

  2. 为 Foo 中的每条记录用一条记录填充临时 table,连接到 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. 清空现有柱 table 并用临时 table - INSERT INTO Bar (id, field1, field2, field3) SELECT id, field1, field2, field3 FROM Bar_copy

  5. 中的记录重新填充
  6. 更新 Foo 中的外键值 - UPDATE Foo SET PrizeGroupId = id

当然,先备份!