У меня есть таблица Pools, где мне нужно показать сумму дочерних элементов каждому родителю. Если родитель внука имеет значение, чем исключить значение внука из суммы
Сценарий таблицы и данные
CREATE TABLE [dbo].[Pools](
[id] [int] NULL,
[Pool] [varchar](50) NULL,
[ParentPool] [varchar](50) NULL,
[Amount] [int] NULL
)
INSERT [dbo].[Pools] ([id], [Pool], [ParentPool], [Amount]) VALUES (1, N'ROOT', NULL, NULL)
GO
INSERT [dbo].[Pools] ([id], [Pool], [ParentPool], [Amount]) VALUES (2, N'Pool 1', N'ROOT', 10000)
GO
INSERT [dbo].[Pools] ([id], [Pool], [ParentPool], [Amount]) VALUES (3, N'Pool 1.1', N'Pool 1', NULL)
GO
INSERT [dbo].[Pools] ([id], [Pool], [ParentPool], [Amount]) VALUES (4, N'Pool 1.2', N'Pool 1', 2000)
GO
INSERT [dbo].[Pools] ([id], [Pool], [ParentPool], [Amount]) VALUES (5, N'Pool 1.3', N'Pool 1', NULL)
GO
INSERT [dbo].[Pools] ([id], [Pool], [ParentPool], [Amount]) VALUES (6, N'Pool 1.3.1', N'Pool 1.3', NULL)
GO
INSERT [dbo].[Pools] ([id], [Pool], [ParentPool], [Amount]) VALUES (7, N'Pool 1.3.2', N'Pool 1.3', 500)
GO
INSERT [dbo].[Pools] ([id], [Pool], [ParentPool], [Amount]) VALUES (8, N'Pool 1.3.3', N'Pool 1.3', 5000)
GO
INSERT [dbo].[Pools] ([id], [Pool], [ParentPool], [Amount]) VALUES (9, N'Pool 2', N'ROOT', 35000)
GO
INSERT [dbo].[Pools] ([id], [Pool], [ParentPool], [Amount]) VALUES (10, N'Pool 2.1', N'Pool 2', 28000)
GO
INSERT [dbo].[Pools] ([id], [Pool], [ParentPool], [Amount]) VALUES (11, N'Pool 3', N'ROOT', NULL)
GO
INSERT [dbo].[Pools] ([id], [Pool], [ParentPool], [Amount]) VALUES (12, N'Pool 3.1', N'Pool 3', 4500)
GO
Как я пытался
WITH CTE AS (
SELECT pool, ParentPool, isnull(Amount,0.0)Amount
FROM Pools
WHERE ParentPool IS NULL
UNION ALL
SELECT t.Pool, t.ParentPool, isnull(t.Amount,0.0)Amount
FROM Pools t
INNER JOIN CTE r ON t.ParentPool = r.pool
WHERE NOT EXISTS (
SELECT 1
FROM Pools t2
WHERE t2.Pool = t.ParentPool
AND isnull(t2.Amount,0.0) > isnull(r.Amount,0.0)
)
)
SELECT Pool, ParentPool, isnull(Amount,0.0)Amount, (
SELECT SUM(isnull(Amount,0.0))
FROM CTE
WHERE Pool IN (
SELECT Pool
FROM CTE
WHERE ParentPool = t.Pool
)
) AS CalculatedAmount
FROM CTE t
Ожидаемый результат
Иллюстрация изображения
Иллюстрация изображения
заранее спасибо
Ответ от @lptr:
Используйте рекурсивный CTE
with c as (
select *,
Pool as cPool,
Amount as cAmount,
case when Amount is not null then 1 else 0 end as stopc,
0 as pAmount,
1 as plvl
from dbo.Pools
union all
select
c.id,
c.Pool,
c.ParentPool,
c.Amount,
p.Pool,
case when c.stopc = 1 then 0 else p.Amount end,
case when c.stopc = 1 or p.Amount is not null then 1 else 0 end,
case when c.plvl = 1 then p.Amount end,
c.plvl + case when p.Amount is null then 0 else 1 end
from c
join dbo.Pools as p on c.cPool = p.ParentPool
)
select
id,
Pool,
ParentPool,
Amount,
case when Amount is null then sum(cAmount) else sum(pAmount) end
from c
group by
id,
Pool,
ParentPool,
Amount;
with c as(select *,Pool as cPool,Amount as cAmount, case when Amount is not null then 1 else 0 end as stopc,0 as pAmount,1 as plvl from dbo.Pools union all select c.id,c.Pool,c.ParentPool,c.Amount,p.Pool,case when c.stopc=1 then 0 else p.Amount end,case when c.stopc=1 or p.Amount is not null then 1 else 0 end ,case when c.plvl=1 then p.Amount end, c.plvl+case when p.Amount is null then 0 else 1 end from c join dbo.Pools as p on c.cPool=p.ParentPool) select id,Pool,ParentPool,Amount,case when Amount is null then sum(cAmount) else sum(pAmount) end from c group by id,Pool,ParentPool,Amount;