2011-04-27 5 views
1

Ma question est basée sur l'article suivant (la table et la fonction hierarchy_connect_by_parent_eq_prior_id) http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/Mysql, arbre, requête hiérarchique, la performance

laisse supposer que la table t_hierarchy a deux champs supplémentaires (à côté id et parent) Typ1 (char) et le temps (int). le champ typ1 peut avoir deux valeurs A et B. Mon but est d'afficher l'arbre entier comme décrit dans l'article mais j'ai besoin d'un champ supplémentaire dans le résultat qui affiche l'heure du nœud courant (si typ1 = B) et de tous ses descendants (si typ1 = B). J'ai donc besoin de la somme de tous les temps des descendants pour un certain nœud (y compris lui-même) quand typ1 = B.

J'ai la solution suivante, mais il est trop lent:

requête principale:

SELECT CONCAT(REPEAT(' ', level - 1), hi.id) AS treeitem, get_usertime_of_current_node_and_descendants(hi.id) as B_time, 
     hierarchy_sys_connect_by_path('/', hi.id) AS path, 
     parent, level 
FROM (
     SELECT hierarchy_connect_by_parent_eq_prior_id(id) AS id, 
       CAST(@level AS SIGNED) AS level 
     FROM (
       SELECT @start_with := 0, 
         @id := @start_with, 
         @level := 0 
       ) vars, t_hierarchy 
     WHERE @id IS NOT NULL 
     ) ho 
JOIN t_hierarchy hi 
ON  hi.id = ho.id 

La fonction get_usertime_of_current_node_and_descendants (entrée int):

BEGIN 
     DECLARE _id INT; 
     DECLARE _desctime INT; 
     DECLARE _nodetime INT; 
     SET _id = input; 

select COALESCE((select sum(time) from (
       SELECT hi.id, time,typ1 
       FROM (
         SELECT hierarchy_connect_by_parent_eq_prior_id_2(id) AS id, @levela AS level 
         FROM (
           SELECT @start_witha := _id, 
             @ida := @start_witha, 
             @levela := 0, 
           ) vars, t_hierarchy a 
         WHERE @ida IS NOT NULL 
         ) ho 
       JOIN t_hierarchy hi 
       ON  hi.id = ho.id 
       ) q where typ1 = 'B'), 0) into _desctime; 
select COALESCE((select time from t_hierarchy where id = _id and typ1='B'), 0) into _nodetime; 
return _desctime + _nodetime; 

END $$ 

La fonction hierarchy_connect_by_parent_eq_prior_id_2 est le comme dans l'article et comme celui ci-dessus hierarchy_connect_by_parent_eq_prior_id mais il a un nom variab global donc il n'interférera pas avec ceux utilisés dans la requête principale.

La solution ci-dessus fonctionne comme vous le souhaitez mais elle est beaucoup trop lente (en particulier lorsque vous travaillez avec des jeux de données volumineux). Pouvez-vous proposer une meilleure solution ou pouvez-vous suggérer comment améliorer la requête? Merci d'avance pour votre temps et votre aide!

+0

Vous souhaitez utiliser des ensembles imbriqués. – Bytemain

+0

Malheureusement, l'utilisation d'ensembles imbriqués n'est pas une option. – ltblueberry

+0

Vous pouvez utiliser une profondeur d'arborescence fixe, par exemple 4, puis utiliser des jointures dans la requête. Je l'ai fait pour un arbre adjacent de profondeur 4 et il devrait être plus rapide que recursivley interroger l'arbre. Bien sûr, ça a l'air moche et ce n'est pas si flexible. – Bytemain

Répondre

0

J'ai résolu le problème de récupération de l'heure des descendants en dehors de mysql (avant d'insérer les entrées dans la table).

+0

Je sais que vous ne pouvez pas voter mais pouvez-vous accepter ma réponse? Je vous suggère d'utiliser une profondeur fixe et je pense que ce n'est pas une réponse sans valeur! Je vous remercie! – Bytemain

+0

Le commentaire/réponse ne convient pas au cas décrit ci-dessus car il ne s'agit pas d'un arbre de profondeur fixe. L'arbre de l'article lié n'est pas non plus un arbre de profondeur fixe. La profondeur est variable. Mais si c'était un arbre de profondeur fixe, j'utiliserais probablement votre solution. Je n'avais certainement pas l'intention d'ignorer ou de discréditer votre réponse. – ltblueberry

+0

Ce n'est pas une bonne réponse mais sachez que je sais que je ne vous aiderai plus. – Bytemain

Questions connexes