2010-10-08 5 views
6

J'ai une table existante qui ressemble à ceci. Le nombre de barres à foo est exactement deux en réalitéDans MySQL, comment séparer une table existante en plusieurs nouvelles tables liées?

table foo_old 
ID   int 
name   string 
bar_name_1 string 
bar_code_1 int 
bar_name_2 string 
bar_code_2 int 

Et puisque cela me fait pleurer, je veux diviser en deux tables comme celui-ci

table foo_new 
ID   int 
name   string 
ID_bar_1  int 
ID_bar_2  int 

table bar_new 
ID   int 
name   string 
code   int 

Ma question est, comment puis-je écrire un script qui va créer un enregistrement correspondant dans foo_new pour chaque existant dans foo_old, y compris les nouveaux ID pour les nouveaux enregistrements bar_new associés?

+0

peut "code" identifier un "bar" pour son "foo"? – MatTheCat

+0

J'aurais dû choisir un nom plus clair comme «pays», car dans ma situation il n'y a pas de clé unique «en réalité» pour la barre – Matt

Répondre

6

d'abord créer les foo_new et bar_new tables:

CREATE TABLE foo_new (
    id int NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    name varchar(100), 
    id_bar_1 int, 
    id_bar_2 int 
); 

CREATE TABLE bar_new (
    id int NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    name varchar(100), 
    code int, 
    UNIQUE (code) 
); 

Ensuite, remplissez le tableau bar_new avec toutes les barres distinctes de la foo_old:

INSERT INTO bar_new (name, code) 
SELECT DISTINCT bar_name_1 name, bar_code_1 code FROM foo_old 
UNION 
SELECT DISTINCT bar_name_2 name, bar_code_2 code FROM foo_old; 

Alors rejoignez foo_old avec bar_new pour remplir foo_new:

INSERT INTO `foo_new` (name, id_bar_1, id_bar_2) 
SELECT f.name, b1.id, b2.id 
FROM foo_old f 
JOIN bar_new b1 ON (b1.code = f.bar_code_1) 
JOIN bar_new b2 ON (b2.code = f.bar_code_2); 

Cas de test:

CREATE TABLE foo_old (
    id int NOT NULL PRIMARY KEY, 
    name varchar(100), 
    bar_name_1 varchar(100), 
    bar_code_1 int, 
    bar_name_2 varchar(100), 
    bar_code_2 int 
); 

INSERT INTO foo_old VALUES (1, 'foo1', 'bar1', 1, 'bar2', 2); 
INSERT INTO foo_old VALUES (2, 'foo2', 'bar6', 6, 'bar5', 5); 
INSERT INTO foo_old VALUES (3, 'foo3', 'bar4', 4, 'bar3', 3); 
INSERT INTO foo_old VALUES (4, 'foo4', 'bar2', 2, 'bar7', 7); 
INSERT INTO foo_old VALUES (5, 'foo5', 'bar6', 6, 'bar5', 5); 
INSERT INTO foo_old VALUES (6, 'foo6', 'bar4', 4, 'bar1', 1); 
INSERT INTO foo_old VALUES (7, 'foo7', 'bar7', 7, 'bar4', 4); 
INSERT INTO foo_old VALUES (8, 'foo8', 'bar3', 3, 'bar8', 8); 

Voici comment foo_new et bar_new ressemblera après l'opération ci-dessus:

SELECT * FROM foo_new ORDER BY name; 
+----+------+----------+----------+ 
| id | name | id_bar_1 | id_bar_2 | 
+----+------+----------+----------+ 
| 3 | foo1 |  1 |  4 | 
| 6 | foo2 |  2 |  7 | 
| 5 | foo3 |  3 |  6 | 
| 4 | foo4 |  4 |  5 | 
| 7 | foo5 |  2 |  7 | 
| 1 | foo6 |  3 |  1 | 
| 2 | foo7 |  5 |  3 | 
| 8 | foo8 |  6 |  8 | 
+----+------+----------+----------+ 
8 rows in set (0.00 sec) 


SELECT * FROM bar_new ORDER BY name; 
+----+--------+------+ 
| id | name | code | 
+----+--------+------+ 
| 1 | bar1 | 1 | 
| 4 | bar2 | 2 | 
| 6 | bar3 | 3 | 
| 3 | bar4 | 4 | 
| 7 | bar5 | 5 | 
| 2 | bar6 | 6 | 
| 5 | bar7 | 7 | 
| 8 | bar8 | 8 | 
+----+--------+------+ 
8 rows in set (0.00 sec) 
+0

Impressionnant! J'ai dû faire quelques légers changements depuis, mon mauvais pour ne pas être clair, le code n'est pas une clé. Heureusement, je peux ajouter un, donc ma solution finale ressemble à ce INSERT INTO bar_new (nom, code, id_foo) nom SELECT bar_name_1, bar_code_1, le code id de foo_old UNION ALL SELECT nom de bar_name_2, bar_code_2, le code id de foo_old INSERT INTO 'foo_new' (nom, id_bar_1, id_bar_2) SELECT f.name, b1.id, b2.id DE foo_old f REJOIGNEZ bar_new b1 ON (b1.id_foo = f.id) ET (b1 .name = f.bar_name_1) REJOIGNEZ bar_new b2 ON (b2.id_foo = f.id) ET (b2.name = f.bar_name_2) – Matt

+0

sérieusement les gens doivent cesser d'utiliser foo bar et juste créer des exemples raisonnables. cela entrave vraiment la capacité à comprendre le problème. – AndrewMcLagan

Questions connexes