2009-06-08 4 views
2

Je cherche une requête efficace pour retourner les nœuds enfants d'un arbre. La structure de données est:Requête efficace pour obtenir tous les nœuds enfants d'un arbre (mysql)

`ct_cid` int(10) unsigned NOT NULL default '0', // the data 
    `ct_level` int(10) unsigned NOT NULL default '0', // the level (0 = topmost) 
    `ct_parent` int(10) unsigned NOT NULL default '0', // parent ct_cid 

J'ai besoin pour vous assurer qu'il ne sera pas des boucles sans fin, même si l'arbre est cassé ou deux noeuds pointent vers l'autre en tant que parent.

Répondre

0

J'utilise sql query, puis je parcourt tous les enregistrements pour créer l'ensemble de données requis.

SELECT 
     * 
    FROM 
     category 
    ORDER BY 
     name ASC 

puis

Cela doit vous aider!

+0

Ci-dessus exmaple est en PHP. Vous pouvez extraire une arborescence en utilisant $ categoryData ['parents'] [$ category_id]. – TigerTiger

+1

Ne semble pas être très efficace. – Nir

4

Voir cette entrée dans mon blog sur la façon de le faire efficacement dans MySQL:

Vous aurez besoin de créer deux fonctions:

CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_id_with_level_and_loop(value INT, maxlevel INT) RETURNS INT 
NOT DETERMINISTIC 
READS SQL DATA 
BEGIN 
     DECLARE _id INT; 
     DECLARE _parent INT; 
     DECLARE _next INT; 
     DECLARE _i INT; 
     DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL; 

     SET _parent = @id; 
     SET _id = -1; 
     SET _i = 0; 

     IF @id IS NULL THEN 
       RETURN NULL; 
     END IF; 

     LOOP 
       SELECT MIN(id) 
       INTO @id 
       FROM t_hierarchy 
       WHERE parent = _parent 
         AND id > _id 
         -- Checking for @start_with in descendants 
         AND id <> @start_with 
         AND COALESCE(@level < maxlevel, TRUE); 
       IF @id IS NOT NULL OR _parent = @start_with THEN 
         SET @level = @level + 1; 
         RETURN @id; 
       END IF; 
       SET @level := @level - 1; 
       SELECT id, parent 
       INTO _id, _parent 
       FROM t_hierarchy 
       WHERE id = _parent; 
       SET _i = _i + 1; 
     END LOOP; 
     RETURN NULL; 
END 

et

CREATE FUNCTION hierarchy_connect_by_iscycle(node INT) RETURNS INT 
NOT DETERMINISTIC 
READS SQL DATA 
BEGIN 
     DECLARE _id INT; 
     DECLARE _loop INT; 
     DECLARE _node INT; 
     DECLARE EXIT HANDLER FOR NOT FOUND RETURN 0; 
     SET _id = COALESCE(node, @id); 
     SET _loop = 0; 
     SET _node = 0; 
     LOOP 
       SELECT parent 
       INTO _id 
       FROM t_hierarchy 
       WHERE id = _id; 
       IF _id = @start_with THEN 
         SET _loop := _loop + 1; 
       END IF; 
       IF _id = COALESCE(node, @id) THEN 
         SET _node = _node + 1; 
       END IF; 
       IF _loop >= 2 THEN 
         RETURN _node; 
       END IF; 
     END LOOP; 
END 

qui imiterait l » CONNECT BY et CONNECT_BY_ISCYCLEOracle, et de les utiliser dans une requête:

SELECT CONCAT(REPEAT(' ', lvl - 1), hi.id) AS treeitem, 
     hierarchy_sys_connect_by_path('/', hi.id) AS path, 
     parent, lvl, 
     CASE 
      WHEN lvl >= @maxlevel THEN 1 
      ELSE COALESCE(
      (
      SELECT 0 
      FROM t_hierarchy hl 
      WHERE hl.parent = ho.id 
        AND hl.id <> @start_with 
      LIMIT 1 
      ), 1) 
     END AS is_leaf, 
     hierarchy_connect_by_iscycle(hi.id) AS is_cycle 
FROM (
     SELECT hierarchy_connect_by_parent_eq_prior_id_with_level_and_loop(id, @maxlevel) AS id, 
       CAST(@level AS SIGNED) AS lvl 
     FROM (
       SELECT @start_with := 97657, 
         @id := @start_with, 
         @level := 0, 
         @maxlevel := NULL 
       ) vars, t_hierarchy 
     WHERE @id IS NOT NULL 
     ) ho 
JOIN t_hierarchy hi 
ON  hi.id = ho.id 
1

Ceci est mon problème. Requête récursive.

function select_child_ids($parent_id,&$ida) { 

    global $sql; 

    $items = $sql->select_column("SELECT id FROM test WHERE parent_id = ".$parent_id); 

    if ($items) { 
     foreach ($items as $id) { 
      $ida[] = $id; 
      select_child_ids($id,$ida); 
     } 
    } else { 
     return false; 
    } 
} 

Remarque $ sql est un exemple de ma classe pour travailler avec mysql. Vous pouvez utiliser le vôtre. Après l'exécution, vous pouvez lire les éléments childs dans le tableau $ ida

+0

Je pense que l'OP voulait une solution MySQL pure, pas une fonction PHP récursive. Cela pourrait probablement encore être utile pour certains, cependant. – John

Questions connexes