J'ai besoin de recalculer les quantités dans une structure de nomenclature qui ne garantit que les valeurs de quantité correctes pour les nœuds feuilles.Calcul des valeurs agrégées dans une structure hiérarchique bottom-up
Si ce qui précède est un peu flou, ne vous inquiétez pas, voici un exemple simplifié.
Considérons une table hiérarchique définissant trois colonnes: ID (PK), PID (ID parent dans la hiérarchie) et Q (quantité - de quelque chose, pour l'enregistrement en cours). La colonne ord
sert uniquement à trier les résultats. La colonne lvl
définit le niveau de l'enregistrement en cours dans la hiérarchie.
Pour ceux qui se demandent comment ces colonnes sont maintenues, la table @results est peuplée dans le monde réel par une fonction qui fait toutes les astuces; pour cet exemple, ils recevront des valeurs codées en dur.
Maintenant, le problème est que les valeurs Q correctes sont garanties uniquement pour les nœuds de niveau feuille dans la hiérarchie. Pour les autres nœuds Q peut ou peut ne pas être correctement défini. Ma tâche consiste à recalculer les valeurs Q pour ces nœuds.
données Exemple:
insert into @results(ord, lvl, ID, PID, Q)
select 1, 0, 'A' as ID, null as PID, null as Q union
select 2, 1, 'B' , 'A' , 15 union
select 3, 1, 'C' , 'A' , 10 union
select 4, 2, 'B1' , 'B' , 6 union
select 5, 2, 'B2' , 'B' , 4 union
select 6, 2, 'C1' , 'C' , 5 union
select 7, 2, 'C2' , 'C' , 3 union
select 8, 3, 'C11', 'C1', 4 union
select 9, 3, 'C12', 'C1', 3
Comme vous pouvez le voir, les quantités pour B et C1 sont mal: ils sont 15 et 5, mais devraient être 10 et 7:
select * from @results order by ord
Voici la données initiales:
ID PID Q lvl ord
---- ---- ----------- ----------- -----------
A NULL NULL 0 1
B A 15 1 2
C A 10 1 3
B1 B 6 2 4
B2 B 4 2 5
C1 C 5 2 6
C2 C 3 2 7
C11 C1 4 3 8
C12 C1 3 3 9
Enfin, la question suivante: est-il possible de mettre à jour ce tableau dans un SEt- manière basée de sorte que toutes les quantités sont mises à jour avec des quantités additionnées ascendantes de nœuds enfants?
Le meilleur que je suis venu avec on peut le voir ci-dessous, mais il est pas encore défini basé:
declare @level int
select @level = max(lvl) from @results
while (@level > 0)
begin
update r set Q = s.SumQ
from @results r inner join (
select PID, sum(Q) as SumQ
from @results
where lvl = @level group by PID
) s on (r.ID = s.PID)
set @level = @level - 1
end
select * from @results
qui donne les quantités correctes:
ID PID Q lvl ord
---- ---- ----------- ----------- -----------
A NULL 20 0 1
B A 10 1 2
C A 10 1 3
B1 B 6 2 4
B2 B 4 2 5
C1 C 7 2 6
C2 C 3 2 7
C11 C1 4 3 8
C12 C1 3 3 9
Merci!
+1 coz 'ça marche mais je vais devoir le mâcher pendant un moment :) –