2011-01-23 2 views
2

J'ai une table categories qui ressemble à ceci:Comment joindre ces 2 tables ensemble (MySQL, requête hiérarchique)?

id | name  | parent  
-----------------------  
1 | Toys  | 1 
2 | Clothing | 1 
3 | Kid's Toys | 0 

J'ai une autre table appelée category_relationships qui ressemble à ceci:

id | category_id | parent_id  
----------------------------  
1 | 3   | 1 

Je veux avoir la sortie suivante:

Catégories :

Toys 
    - Kid's Toys 
Clothing 

Comment y parvenir avec une requête?

+2

Une requête hiérarchique - ouch ... va être difficile. Si vous ne connaissez pas la profondeur maximale de la hiérarchie, vous ne pouvez pas coder une solution générale à moins que le SGBD ne prenne en charge la clause 'WITH RECURSIVE' (ou les extensions non standard telles que 'CONNECT BY'). –

+0

Oui, connaissez-vous la profondeur maximale de l'arbre? – Xailor

Répondre

0

Une meilleure/bonne réponse/solide sera probablement créer une procédure MySQL pour cela, mais si vos données peuvent tenir dans ces limites, vous pouvez utiliser le ci-dessous:

  • pas plus de 5 niveaux (ou étendre le modèle selon les besoins)
  • ID sont pas plus de 6 chiffres (ou modifier les expressions concat)

Cette requête utilise Concat pour construire une référence triables afin que les enfants de a viennent après a, etc. les noms sont indentés manuellement en utilisant des espaces de concat et de début.

select concat(1000000 + a.id, '|') SORT 
      ,a.name 
    from categories a 
    where a.parent = 1 # top level parents only 
union all 
    select concat(1000000 + a.id, '|', 
      1000000 + IFNULL(b.id,0), '|') 
      ,concat(' - ', b.name) 
    from categories a 
    inner join category_relationships a1 on a1.parent_id = a.id 
    inner join categories b on b.id = a1.category_id 
    where a.parent = 1 
union all 
    select concat(1000000 + a.id, '|', 
      1000000 + IFNULL(b.id,0), '|', 
      1000000 + IFNULL(c.id,0), '|') 
      ,concat(' - ', c.name) 
    from categories a 
    inner join category_relationships a1 on a1.parent_id = a.id 
    inner join categories b on b.id = a1.category_id 
    inner join category_relationships b1 on b1.parent_id = b.id 
    inner join categories c on c.id = b1.category_id 
    where a.parent = 1 
union all 
    select concat(1000000 + a.id, '|', 
      1000000 + IFNULL(b.id,0), '|', 
      1000000 + IFNULL(c.id,0), '|', 
      1000000 + IFNULL(d.id,0), '|') 
      ,concat('  - ', d.name) 
    from categories a 
    inner join category_relationships a1 on a1.parent_id = a.id 
    inner join categories b on b.id = a1.category_id 
    inner join category_relationships b1 on b1.parent_id = b.id 
    inner join categories c on c.id = b1.category_id 
    inner join category_relationships c1 on c1.parent_id = c.id 
    inner join categories d on d.id = c1.category_id 
    where a.parent = 1 
union all 
    select concat(1000000 + a.id, '|', 
      1000000 + IFNULL(b.id,0), '|', 
      1000000 + IFNULL(c.id,0), '|', 
      1000000 + IFNULL(d.id,0), '|', 
      1000000 + IFNULL(e.id,0)) 
      ,concat('  - ', e.name) 
    from categories a 
    inner join category_relationships a1 on a1.parent_id = a.id 
    inner join categories b on b.id = a1.category_id 
    inner join category_relationships b1 on b1.parent_id = b.id 
    inner join categories c on c.id = b1.category_id 
    inner join category_relationships c1 on c1.parent_id = c.id 
    inner join categories d on d.id = c1.category_id 
    inner join category_relationships d1 on d1.parent_id = d.id 
    inner join categories e on e.id = d1.category_id 
    order by SORT