我无法弄清楚如何编写一个CTE,它将成本从事务表汇总到一个自联接表,这样它就可以在层次结构的每个级别给出总成本。我汇总了一个非常简单的例子来说明问题。 以下是DDL和插入脚本,因此您可以重现这个问题,如果您非常友好地帮助我:
With cteAggregateCost
as
(
select i.itemId, i.ParentId, t.Amount
from Items i join Transactions t on i.ItemId = t.ItemId
union all
select i.itemId, i.ParentId, t.Amount
from Items i join cteAggregateCost c on i.ItemId = c.ParentId
join Transactions t on i.ItemId = t.ItemId
)
select i.ParentId, i.ItemId, i.ItemName, sum(Amount) As AggregateCost
from Items i left join cteAggregateCost c on i.ItemId = c.ItemId
group by i.ParentId, i.ItemId, i.ItemName
以下是我一直在研究的CTE:
0
这是我得到的结果:
这是我希望得到的结果:
正如您所看到的,除了前两行之外,所有行都在工作,这些行没有容器的成本,只有它们包含的项目。
非常感谢您提供的任何方向!
答案 0 :(得分:2)
您可以像这样使用recursive CTE
;WITH temp AS
(
SELECT i.*, sum(isnull(t.Amount,0)) AS Amount
FROM @Items i
LEFT JOIN @Transactions t ON t.ItemId = i.ItemId
GROUP BY i.ItemId, i.ParentId, i.ItemName
)
,cteAggregateCost
as
(
select i.ItemId, i.ItemId AS RootId, i.Amount
from temp i
union all
select i.ItemId, c.RootId, i.Amount
from cteAggregateCost c
INNER JOIN temp i ON i.ParentId = c.ItemId
)
select i.*, ca.TotalAmount
from @Items i
CROSS APPLY
(
SELECT Sum(cac.Amount) AS TotalAmount
FROM cteAggregateCost cac WHERE i.ItemId = cac.RootId
) ca
OPTION (MAXRECURSION 0)
答案 1 :(得分:1)
谢谢你,TriV。你的答案很棒!但是,我确实找到了Xi Jin on the SQL Server forum发布的更简单的答案。这是他的解决方案:
With cteAggregateCost
as
(
select i.itemId as rootid,i.itemid, i.ParentId
from Items i
union all
select rootid, i.itemId, i.ParentId
from Items i join cteAggregateCost c on i.ParentId = c.ItemId
)
select a.parentid, a.ItemId , a.ItemName , sum(t.Amount) As AggregateCost
from items a
left join cteAggregateCost i on a.itemid = i.rootid
left join Transactions t on i.ItemId = t.ItemId
group by a.parentid, a.ItemId, a.ItemName
当针对具有多层次关系的更大数据集进行测试时,两种解决方案都能提供与我所寻找的相同的正确结果。对我来说,习琳的回答更容易理解。我无法解决如何添加rootID技术,该技术保留了没有自己成本的项目的值,只有子项目的成本。