Comment recomposer une hiérarchie dans une table?

J'ai deux tables

voitures : contient des données sur la hiérarchie des voitures

+-----+-------------+-----------+ | id | description | parent_id | +-----+-------------+-----------+ | 1 | All cars | 1 | | 30 | Toyota | 1 | | 34 | Yaris | 30 | | 65 | Yaris | 30 | | 87 | Avensis | 30 | | 45 | Avensis | 30 | | 143 | Skoda | 1 | | 199 | Octavia | 143 | | 12 | Yeti | 143 | +-----+-------------+-----------+ 

car_mapping : contient des données de mappage lorsque des voitures en double (avec des ID différents) sont mappées sur un ID.

 +--------+----------+--------+ | car_id | car_name | map_id | +--------+----------+--------+ | 34 | Yaris | 1 | | 65 | Yaris | 1 | | 87 | Avensis | 2 | | 45 | Avensis | 2 | | 199 | Octavia | 3 | | 12 | Yeti | 4 | | 30 | Toyota | 5 | | 143 | Skoda | 6 | | 1 | All cars | 0 | +--------+----------+--------+ 

Maintenant, l'idée est de créer une troisième table, cars_new , basée sur les voitures et car_mapping qui supprime les duplicates et re-keys de la hiérarchie dans la table cars en fonction du champ map_id dans la table car_mapping . Voici la résultante cars_new :

 +--------+----------+---------------+ | map_id | car_name | parent_map_id | +--------+----------+---------------+ | 0 | All | 0 | | 1 | Yaris | 5 | | 2 | Avensis | 5 | | 3 | Octavia | 6 | | 4 | Yeti | 6 | | 5 | Toyota | 0 | | 6 | Skoda | 0 | +--------+----------+---------------+ 

Voici le Fiddle SQL pour cette question. Des idées pour recomposer cette hiérarchie?

 select distinct cm.map_id, cm.car_name, cm2.map_id parent_map_id from cars c, car_mapping cm, car_mapping cm2 where c.id = cm.car_id and c.parent_id = cm2.car_id(+) order by cm.map_id; 

PS: dans votre table car_mapping , vous avez besoin d'une ligne supplémentaire (la première ci-dessous) pour get exactement le résultat que vous voulez:

 +--------+----------+--------+ | car_id | car_name | map_id | +--------+----------+--------+ | 1 | All | 0 | | 34 | Yaris | 1 | | 65 | Yaris | 1 | Etc.. 

Basé sur la réponse acceptée de @Majid LAISSI, cela semble fonctionner à la fois dans Oracle et SQL Server:

 select distinct cm.map_id, cm.car_name, cm2.map_id as parent_map_id from cars c left outer join car_mapping cm on c.id = cm.car_id left outer join car_mapping cm2 on c.parent_id = cm2.car_id order by cm.map_id; 

Vous n'avez pas de hiérarchie, et vous feriez mieux de ne pas en créer un. Observez que votre tableau "voitures" ne décrit pas les voitures; il affecte simplement une string à un nombre (et un autre nombre à ce nombre). Dès le départ, «toutes les voitures» n'est pas une voiture, et «Toyota» est un constructor automobile, pas une voiture.

La solution – qui aiderait à résoudre votre problème d'unicité et simplifier vos requêtes – consiste à utiliser une table pour chaque chose distincte:

  • fabrique {mfg_id, name} – par exemple GM, Ford
  • fait {make_id, name, mfg_id} – par exemple Chevrolet, Lincoln; liens vers des manufactures
  • templates {name, make_id} – par exemple Yaris, etc .; liens vers des marques.

Assurez-vous de rendre "nom" unique dans chacune des tables pour empêcher la création de faux ID.

Cela vous permettra d'assigner de nouveaux attributes à ces choses au fur et à mesure qu'elles se présentent, telles que les années où elles ont été faites ou combien ont été vendues, ou combien de portes chaque model entre en jeu. Cela vous permettra aussi d'éviter les "relations" , disons, faire de la Yaris le parent de "toutes les voitures".

(BTW, je suggère que vous évitez "carte" ou "mapping" dans un nom de table, car il ne dit rien, chaque table relie les éléments de la rangée les uns aux autres.Chaque table mappe la key de ses valeurs. les nouvelles sont que votre table car_mapping disparaît dans le nouveau design.)

Quant à savoir comment convertir la table des voitures existantes, ce sera une nuisance. En supposant que cars_mapping est correct, vous pourrez insert dans chaque table, en y joignant et en prenant le min (id) en groupant par nom. Vous aurez besoin de trois de ces requêtes, suivies d'un regard attentif pour vérifier, er, désalignment.