2012-03-17 2 views
3

Je suit la configuration de base de données existante:relation ManyToMany fixation

CREATE TABLE `categories` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(50) NOT NULL, 
    PRIMARY KEY (`id`) 
) 

CREATE TABLE `items` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(50) NOT NULL, 
    `category_ids` varchar(50) NOT NULL, 
    PRIMARY KEY (`id`) 
) 

dans lequel category_ids est une chaîne de séparés par comas de catégorie id: 1, 10, 15, 6. Existe-t-il un moyen de convertir cette base de données en plus conventionnelle (en utilisant trois tables, une pour stocker les relations), en utilisant uniquement SQL et aucun autre script?

Répondre

1

MySQL n'a pas de CTE CROSS APPLY ou récursif, ce qui serait le chemin le plus simple.

Mais vous n'êtes que dong cette fois, donc vous avez seulement besoin d'un hack rapide.

Tout d'abord, connaître le nombre maximum d'éléments dans la liste des catégories ...

SELECT 
    MAX(LEN(category_ids) - LEN(REPLACE(category_ids, ',', '')) + 1) AS max_items 
FROM 
    items 

Ensuite, vous pouvez faire quelque chose comme ça ...

SELECT 
    items.id, 
    SUBSTRING_INDEX(
    SUBSTRING_INDEX(
     items.category_ids, 
     ',', 
     map.id -- Get the first 'n' items from the list 
    ), 
    ',', 
    -1  -- Get the last item from (the first 'n' items from the list) 
) AS category_id 
FROM 
    items 
INNER JOIN 
(
      SELECT 1 as id 
    UNION ALL SELECT 2 as id 
    UNION ALL SELECT 3 as id 
    etc, etc, up to the max number of items found previously 
) 
    AS map 
    ON LEN(items.category_ids) - LEN(REPLACE(items.category_ids, ',', '')) + 1 >= map.id 

Je ne l'ai pas testé , mais je suppose que SUBSTRING_INDEX('last', ',', -1) renvoie 'last'.

Je ne suis pas expert MySQL, donc ce ne pas être optimal, mais comme un temps rapide gagner thistype de la structure devrait fonctionner ...

+0

Je souhaite qu'il y ait un moyen de générer table de carte indépendante du nombre max . Maintenant, il semble fonctionner, mais pas de manière optimale, mais qui s'en soucie tant que cela fonctionne? :) – Shark

+0

BTW, nous pouvons utiliser 'UNION' au lieu de' UNION ALL' et MySQL actuellement n'ont pas de fonction 'LEN', c'est' LONGUEUR 'là. – Shark

+1

@Shark - Union a ajouté un surcoût de déduplication. Union Tout ne fait pas. Si vous ne vous souciez pas de la déduplication, ou si vous en avez besoin, il est conseillé d'utiliser Union All. – MatBailie

Questions connexes