Ваши существующие данные результатов заставляют меня думать, что вы, возможно, уже используете какую-то рекурсивную CTE для создания таких вещей, как Level
и Name
. Если это так, то, вероятно, его можно адаптировать для одновременного вычисления hier
.
Но если нет, мы используем рекурсивный CTE для построения наших hier
столбцов, а затем используем IsDescendantOf
при вычислении сумм:
declare @t table(ID int, Name varchar(30), ParentID int, Level int, Amount int)
insert into @t(ID ,Name , ParentID , Level , Amount) values
(1 ,'ITEM 1 ',NULL, 0 ,100 ),
(3 ,' - Item 1-1 ', 1, 1 ,100 ),
(7 ,' - - Item 1-1-1', 3, 2 ,100 ),
(8 ,' - - Item 1-1-2', 3, 2 ,100 ),
(4 ,' - Item 1-2 ', 1, 1 ,100 ),
(9 ,' - - Item 1-2-1', 4, 2 ,100 ),
(10 ,' - - Item 1-2-2', 4, 2 ,100 ),
(2 ,'ITEM 2 ',NULL, 0 ,200 ),
(5 ,' - Item 2-1 ', 2, 1 ,200 ),
(11 ,' - - Item 2-1-1', 5, 2 ,200 ),
(12 ,' - - Item 2-1-2', 5, 2 ,200 ),
(6 ,' - Item 2-2 ', 2, 1 ,200 ),
(13 ,' - - Item 2-2-1', 6, 2 ,200 ),
(14 ,' - - Item 2-2-2', 6, 2 ,200 )
;With hierarchy as (
select ID, Name, '/' + CONVERT(varchar(max),ID) + '/' as hier,Amount
from @t
where ParentID is null
union all
select t.ID,t.Name, hier + CONVERT(varchar(max),t.ID) + '/',t.Amount
from
hierarchy h
inner join
@t t
on
t.ParentID = h.ID
), Typed as (
select ID,Name,Amount,CONVERT(hierarchyid,hier) as hier
from hierarchy
)
select
*
from
Typed t1
cross apply
(select SUM(Amount) as GroupTotal from Typed t2
where t2.hier.IsDescendantOf(t1.hier) = 1) u
order by hier
Результаты:
ID Name Amount hier GroupTotal
----------- ------------------------------ ----------- ------------- -----------
1 ITEM 1 100 0x58 700
3 - Item 1-1 100 0x5BC0 300
7 - - Item 1-1-1 100 0x5BE7 100
8 - - Item 1-1-2 100 0x5BE880 100
4 - Item 1-2 100 0x5C20 300
9 - - Item 1-2-1 100 0x5C34C0 100
10 - - Item 1-2-2 100 0x5C3540 100
2 ITEM 2 200 0x68 1400
5 - Item 2-1 200 0x6C60 600
11 - - Item 2-1-1 200 0x6C75C0 200
12 - - Item 2-1-2 200 0x6C7640 200
6 - Item 2-2 200 0x6CA0 600
13 - - Item 2-2-1 200 0x6CB6C0 200
14 - - Item 2-2-2 200 0x6CB740 200
На этом этапе вы также можете решить, что ваша модель данных должна быть изменена таким образом, чтобы иерархия напрямую моделировалась с использованием типа hierarchyid
, а не Parent / Child. Это зависит от того, в каких других случаях эти данные должны удовлетворять.
Проблема здесь в том, что большинство иерархических запросов, как правило, в конечном итоге исследуют иерархию сверху вниз, но нужные данные легко получить снизу вверх. Я попытался выяснить, существует ли умное выражение GROUP BY
или ORDER BY
(последнее для использования в оконной функции), которое также может использовать IsDescendantOf
, но не удалось.