简体   繁体   English

将一对多关系转换为一对一关系 MySQL

[英]Convert One to Many to One to One Relationship MySQL

I have two MySQL tables we can call Foo and Bar .我有两个 MySQL 表,我们可以称之为FooBar

Both tables have a column called PrizeGroupId .两个表都有一个名为PrizeGroupId的列。 the goal is to create a one-to-one relationship between these columns, and I have created stored procedures to add/edit Foo that update the corresponding row via the one-to-one relationship in Bar .目标是在这些列之间创建一对一的关系,我已经创建了存储过程来添加/编辑Foo ,通过Bar的一对一关系更新相应的行。

The problem lies in the fact that the data wasn't always structured this way and I need to write a script to convert the data from it's previous state (which I'm about to describe) to a one-to-one relationship based off of PrizeGroupId .问题在于数据并不总是以这种方式构建的,我需要编写一个脚本来将数据从它以前的状态(我将要描述)转换为基于以下的一对一关系的PrizeGroupId

Previously, multiple rows in Foo could have the same PrizeGroupId such that there was a one-to-many relationship between entries in Bar to Foo based off of PrizeGroupId .以前, Foo多行可能具有相同的PrizeGroupId ,因此Bar条目与Foo的条目之间存在一对多关系,基于PrizeGroupId The script that I need to write has to break apart every one-to-many instance of this nature into many (almost identical) one-to-one relationships between Foo and Bar .我需要编写的脚本必须将这种性质的每个一对多实例分解为FooBar之间的许多(几乎相同的)一对一关系。

In principle, I want to:原则上,我想:

  1. Iterate through Foo遍历Foo
  2. See if the current row's PrizeGroupId is not unique in Foo .查看当前行的PrizeGroupIdFoo是否不是唯一的。
  3. Assign it a unique value (perhaps the current items primary key)为其分配一个唯一值(可能是当前项目的主键)
  4. Add a row in Bar with the new PrizeGroupId .使用新的PrizeGroupIdBar添加一行。 Copy over all of the old row's other data into this new row such that it is "nearly identical".将所有旧行的其他数据复制到这个新行中,使其“几乎相同”。
  5. After all is said and done, remove the old one-to-many row from Bar .毕竟,从Bar删除旧的一对多行。

I understand the problem and how I could do this in pseudocode in a programming language, however I am still learning MySQL and am not sure how to go about solving a problem of this nature.我理解这个问题,以及我如何用编程语言的伪代码来做到这一点,但是我仍在学习 MySQL 并且不确定如何解决这种性质的问题。

If you can provide me with help through MySQL code and/or what steps I can take/read about to go about solving this problem that would be, or at least point me to the kind of reading/SO question related to this kind of problem that would be appreciated, although I had a difficult time finding particular resources on my own.如果您可以通过 MySQL 代码为我提供帮助和/或我可以采取/阅读哪些步骤来解决这个问题,或者至少向我指出与此类问题相关的阅读/SO 问题这将不胜感激,尽管我自己很难找到特定的资源。

What you are asking for is not that hard.你所要求的并不难。 Some of your thinking is getting in the way.你的一些想法正在妨碍你。 First, one almost never iterates in SQL.首先,在 SQL 中几乎从不迭代。 SQL is not that kind of language. SQL 不是那种语言。 Everything in SQL is done via sets of something. SQL 中的一切都是通过一些东西来完成的。

Your approach can be:你的方法可以是:

  1. Identify the set of rows where the PrizeGroupId is already unique and move them to a new copy of the table.确定 PrizeGroupId 已经唯一的行集,并将它们移动到表的新副本。

To create a table, you can use "create table foo2 like foo;".要创建表,您可以使用“create table foo2 like foo;”。 Very useful.很有用。

To identify the rows where PrizeGroupId is already unique, use something like:要识别 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. The rows left in the original table do not have a unique PrizeGroupId.原始表中剩余的行没有唯一的 PrizeGroupId。 Change the PrizeGroupId value so that they are unique.更改 PrizeGroupId 值,使其唯一。

  2. Merge the two sets to reconstruct the table with the original rows and with PrizeGroupId unique.合并这两个集合以使用原始行和唯一的 PrizeGroupId 重建表。

One reason that this is hard is because if you had created the tables with the one-to-one join, you would have used the pk to join the tables.这很难的一个原因是,如果您使用一对一连接创建了表,您将使用 pk 来连接这些表。 The pk is already unique so why use something else. pk 已经是独一无二的,所以为什么要使用其他东西。 Once you have the tables separated and the PrizeGroupId is unique, you might want to think about setting the pk of foo to the pk of bar and then removing the PrizeGroupId column.一旦您将表分开并且 PrizeGroupId 是唯一的,您可能需要考虑将 foo 的 pk 设置为 bar 的 pk,然后删除 PrizeGroupId 列。

What is required is for the Bar table to contain a single record for each record in Foo, and for the PrizeGroupId field in Foo to be unqiue. Bar 表需要为 Foo 中的每条记录包含一条记录,并且 Foo 中的 PrizeGroupId 字段必须是唯一的。 As Foo.Id is already unique, it makes sense to use that as the foreign key.由于 Foo.Id 已经是唯一的,因此将其用作外键是有意义的。

Running a query like SELECT Foo.id, Bar.* FROM Foo INNER JOIN Bar USING (PrizeGroupId) will give us a single record for each record in Foo, along with the data from the corresponding record from Bar.运行像SELECT Foo.id, Bar.* FROM Foo INNER JOIN Bar USING (PrizeGroupId)将为我们提供 Foo 中每条记录的单个记录,以及来自 Bar 相应记录的数据。 So, if we were to replace the data in Bar with what is returned by this query, and then use Foo.Id for PrizeGroupId, we'd acheive what is required.因此,如果我们将 Bar 中的数据替换为此查询返回的数据,然后将 Foo.Id 用于 PrizeGroupId,我们将实现所需的内容。

  1. Create a temporary table with the same structure as Bar - something like CREATE TABLE Bar_copy LIKE Bar创建一个与 Bar 结构相同的临时表 - 类似于CREATE TABLE Bar_copy LIKE Bar

  2. Fill the temporary table with one record for each record in Foo, joined to the corresponding record in Bar - you'll need to list all the columns in Bar, for example - 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)用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. Clear the existing PrizeGroupID field from Foo - UPDATE Foo SET PrizeGroupId = NULL从 Foo 中清除现有的 PrizeGroupID 字段 - UPDATE Foo SET PrizeGroupId = NULL

  4. Empty the existing Bar table and refill it with the records from the temporary table - INSERT INTO Bar (id, field1, field2, field3) SELECT id, field1, field2, field3 FROM Bar_copy清空现有的 Bar 表并用临时表中的记录重新填充它 - INSERT INTO Bar (id, field1, field2, field3) SELECT id, field1, field2, field3 FROM Bar_copy

  5. Update the foreign key values in Foo - UPDATE Foo SET PrizeGroupId = id更新 Foo 中的外键值 - UPDATE Foo SET PrizeGroupId = id

Obviously, take a back-up first!显然,先备份!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM