2010-11-17 6 views
2

J'ai une ancienne base de données avec les enregistrements gazillion (plus ou moins) qui ont une seule colonne tags (avec des étiquettes étant tube délimité) qui ressemble à ceci:Comment diviser une colonne délimitée par des barres et insérer chaque valeur dans une nouvelle table Une fois?

Breakfast 
    Breakfast|Brunch|Buffet|Burger|Cakes|Crepes|Deli|Dessert|Dim Sum|Fast Food|Fine Wine|Spirits|Kebab|Noodles|Organic|Pizza|Salad|Seafood|Steakhouse|Sushi|Tapas|Vegetarian 
    Breakfast|Brunch|Buffet|Burger|Deli|Dessert|Fast Food|Fine Wine|Spirits|Noodles|Pizza|Salad|Seafood|Steakhouse|Vegetarian 
    Breakfast|Brunch|Buffet|Cakes|Crepes|Dessert|Fine Wine|Spirits|Salad|Seafood|Steakhouse|Tapas|Teahouse 
    Breakfast|Brunch|Burger|Crepes|Salad 
    Breakfast|Brunch|Cakes|Dessert|Dim Sum|Noodles|Pizza|Salad|Seafood|Steakhouse|Vegetarian 
    Breakfast|Brunch|Cakes|Dessert|Dim Sum|Noodles|Pizza|Salad|Seafood|Vegetarian 
    Breakfast|Brunch|Deli|Dessert|Organic|Salad 
    Breakfast|Brunch|Dessert|Dim Sum|Hot Pot|Seafood 
    Breakfast|Brunch|Dessert|Dim Sum|Seafood 
    Breakfast|Brunch|Dessert|Fine Wine|Spirits|Noodles|Pizza|Salad|Seafood 
    Breakfast|Brunch|Dessert|Fine Wine|Spirits|Salad|Vegetarian 

Est-il possible on pourrait récupérer chaque tag et l'insérer dans une nouvelle table tag_id | tag_nm en utilisant MySQL seulement?

+0

Les valeurs sont délimitées tuyau? –

+0

Oui, cela représente une colonne sur 20 – Moak

+0

Vous ne pouvez pas simplement récupérer les données et, par exemple, utiliser str_replace() de PHP et créer un fichier dump? –

Répondre

1

Après avoir trouvé il n'y a pas de fonction split officielle, je l'ai résolu le problème en utilisant uniquement MySQL comme ceci:

1: J'ai créé la fonction StrSplit

CREATE FUNCTION strSplit(x varchar(21845), delim varchar(255), pos int) returns varchar(255) 
return replace(
replace(
substring_index(x, delim, pos), 
substring_index(x, delim, pos - 1), 
'' 
), 
delim, 
'' 
); 

Deuxièmement, j'inséré le nouveau balises dans ma nouvelle table (les vrais noms et les colonnes ont changé, pour le garder simple)

INSERT IGNORE INTO tag (SELECT null, strSplit(`Tag`,'|',1) AS T FROM `old_venue` GROUP BY T) 

Rincer et répéter de plus en plus les pos par un pour chaque collumn (dans ce cas, j'avais un maximum de 8) seperators

Troisième pour obtenir la relation

INSERT INTO `venue_tag_rel` 
(Select a.`venue_id`, b.`tag_id` from `old_venue` a, `tag` b 
    WHERE 
    (   
    a.`Tag` LIKE CONCAT('%|',b.`tag_nm`) 
    OR a.`Tag` LIKE CONCAT(b.`tag_nm`,'|%') 
    OR a.`Tag` LIKE CONCAT(CONCAT('%|',b.`tag_nm`),'|%') 
    OR a.`Tag` LIKE b.`tag_nm` 
    ) 
) 
2

Voici ma tentative qui utilise PHP ..., j'imagine que cela pourrait être plus efficace avec une requête MySQL intelligente. J'ai placé la partie de la relation là aussi. Il n'y a pas d'échappement et de vérification d'erreur.

$rs = mysql_query('SELECT `venue_id`, `tag` FROM `venue` AS a'); 
while ($row = mysql_fetch_array($rs)) { 
    $tag_array = explode('|',$row['tag']); 
    $venueid = $row['venue_id']; 
    foreach ($tag_array as $tag) { 
     $rs2 = mysql_query("SELECT `tag_id` FROM `tag` WHERE tag_nm = '$tag'"); 
     $tagid = 0; 
     while ($row2 = mysql_fetch_array($rs2)) $tagid = $row2['tag_id']; 
     if (!$tagid) { 
      mysql_execute("INSERT INTO `tag` (`tag_nm`) VALUES ('$tag')"); 
      $tagid = mysql_insert_id; 
     } 
     mysql_execute("INSERT INTO `venue_tag_rel` (`venue_id`, `tag_id`) VALUES ($venueid, $tagid)"); 
    } 
} 
+0

+1 Yep, quelque chose comme ça. Je pense que le développement d'un script PHP (ou de tout autre langage) sera plus facile à développer et à déboguer que d'essayer de tout faire en code SQL. –

+0

Mais cela ne résout que le problème pour les programmeurs PHP. J'ai ajouté une réponse MYSQL seulement pour référence future. +1 pour répondre, mais n'a pas été testé – Moak