Frage

Bei einer selbstverweisenden Tabelle

Item 
-------------
Id (pk)
ParentId (fk)

Mit einer verknüpften Tabelle von zugehörigen Werten

ItemValue
-------------
ItemId (fk)
Amount

Und einige Beispieldaten

Item                       ItemValues 
Id      ParentId           ItemId      Amount
--------------------       ----------------------
1       null               1           10
2       1                  3           40
3       1                  3           20
4       2                  4           10
5       2                  5           30
6       null
7       6
8       7

Ich brauche einen sproc Item.Id zu nehmen und die direkte Kinder mit Summen aller ItemValue.Amounts für die sie, ihre Kinder und ihre Kinder den ganzen Weg hinunter den Baum zurück.

Zum Beispiel, wenn 1 übergeben wird, würde der Baum 2, 3, 4, 5 werden die direkten Kinder 2, 3 der Ausgang wäre

 ItemId    Amount
 ------------------
 2         40     (values from ItemIds 4 & 5)
 3         60     (values from ItemId 3)

Welche Ansätze sollten angewendet werden, dieses Verhalten zu machen zu erreichen?

Ich erwäge einen CTE verwenden, aber frage mich, ob es eine bessere / schnellere Annäherung ist.

War es hilfreich?

Lösung

Eine rekursive CTE wie dies funktionieren würde, Ihre Hierarchie vorausgesetzt, geht nicht zu tief:

declare @ParentId int;
set @ParentId = 1;

;with 
  Recurse as (
    select 
      a.Id as DirectChildId
    , a.Id
    from Item a 
    where ParentId = @ParentId
    union all
    select
      b.DirectChildId
    , a.Id
    from Item a 
    join Recurse b on b.Id = a.ParentId
    )
select
  a.DirectChildId, sum(b.Amount) as Amount
from Recurse a
left join ItemValues b on a.Id = b.ItemId
group by
  DirectChildId;

Eine nicht-CTE-Methode würde irgendeine Form von Iteration, Cursor-basierte oder auf andere Weise erfordern. Da es sich um eine gespeicherte Prozedur, es ist eine Möglichkeit, und wenn es eine Menge Daten ist rekursiv durch, wäre es wahrscheinlich besser skalieren, so lange, wie Sie die Daten in geeigneter Weise in Scheiben schneiden.

Wenn der Clustered-Index für Id ist, fügen Sie einen nicht gruppierten Index auf ParentId. Als abdeckenden Index, befriedigt sie die anfänglichen w / out eine Lesezeichen-Suche suchen. Der Clustered-Index wird dann mit dem rekursiven helfen beizutreten.

Wenn der Clustered-Index auf ParentId ist bereits statt, fügen Sie einen nicht gruppierten Index auf Id. Gemeinsam werden sie praktisch äquivalent zu dem oben sein. Für ItemValues, können Sie einen Index auf (ItemId) wollen BEINHALTEN (Betrag), wenn die tatsächliche Tabelle breiter als diese ist.

scroll top