Ras*_*mus 22 t-sql sql-server common-table-expression
我在一张桌子上有一个树木结构.该表是一个可以无限嵌套的类别树.每个类别都有一个ProductCount列,用于说明该类别中有多少产品(不是对子类别求和).
Id | ParentId | Name | ProductCount
------------------------------------
1 | -1 | Cars | 0
2 | -1 | Bikes | 1
3 | 1 | Ford | 10
4 | 3 | Mustang | 7
5 | 3 | Focus | 4
Run Code Online (Sandbox Code Playgroud)
我想做一个SQL查询,每个行/类别给我产品的数量,包括子类别中的产品.
上表的输出应该是
Id | ParentId | Name | ProductCount | ProductCountIncludingChildren
--------------------------------------------------------------------------
1 | -1 | Cars | 0 | 21
2 | -1 | Bikes | 1 | 1
3 | 1 | Ford | 10 | 21
4 | 3 | Mustang | 7 | 7
5 | 3 | Focus | 4 | 4
Run Code Online (Sandbox Code Playgroud)
我知道我可能应该使用CTE,但不能让它以它应该的方式工作.
任何帮助表示赞赏!
Mik*_*son 25
您可以使用递归CTE,其中您在锚点部分获取所有行,并在递归部分连接以获取子行.记住锚点部分的原始Id别名RootID,并在分组的主查询中进行求和RootID.
MS SQL Server 2012架构设置:
create table T
(
Id int primary key,
ParentId int,
Name varchar(10),
ProductCount int
);
insert into T values
(1, -1, 'Cars', 0),
(2, -1, 'Bikes', 1),
(3, 1, 'Ford', 10),
(4, 3, 'Mustang', 7),
(5, 3, 'Focus', 4);
create index IX_T_ParentID on T(ParentID) include(ProductCount, Id);
Run Code Online (Sandbox Code Playgroud)
查询1:
with C as
(
select T.Id,
T.ProductCount,
T.Id as RootID
from T
union all
select T.Id,
T.ProductCount,
C.RootID
from T
inner join C
on T.ParentId = C.Id
)
select T.Id,
T.ParentId,
T.Name,
T.ProductCount,
S.ProductCountIncludingChildren
from T
inner join (
select RootID,
sum(ProductCount) as ProductCountIncludingChildren
from C
group by RootID
) as S
on T.Id = S.RootID
order by T.Id
option (maxrecursion 0)
Run Code Online (Sandbox Code Playgroud)
结果:
| ID | PARENTID | NAME | PRODUCTCOUNT | PRODUCTCOUNTINCLUDINGCHILDREN |
|----|----------|---------|--------------|-------------------------------|
| 1 | -1 | Cars | 0 | 21 |
| 2 | -1 | Bikes | 1 | 1 |
| 3 | 1 | Ford | 10 | 21 |
| 4 | 3 | Mustang | 7 | 7 |
| 5 | 3 | Focus | 4 | 4 |
Run Code Online (Sandbox Code Playgroud)
这与汤姆的答案是相同的概念,但代码更少(而且速度更快)。
with cte as
(
select v.Id, v.ParentId, v.Name, v.ProductCount,
cast('/' + cast(v.Id as varchar) + '/' as varchar) Node
from Vehicle v
where ParentId = -1
union all
select v.Id, v.ParentId, v.Name, v.ProductCount,
cast(c.Node + CAST(v.Id as varchar) + '/' as varchar)
from Vehicle v
join cte c on v.ParentId = c.Id
)
select c1.Id, c1.ParentId, c1.Name, c1.ProductCount,
c1.ProductCount + SUM(isnull(c2.ProductCount, 0)) ProductCountIncludingChildren
from cte c1
left outer join cte c2 on c1.Node <> c2.Node and left(c2.Node, LEN(c1.Node)) = c1.Node
group by c1.Id, c1.ParentId, c1.Name, c1.ProductCount
order by c1.Id
Run Code Online (Sandbox Code Playgroud)
SQL Fiddle(我添加了一些额外的数据行进行测试)
| 归档时间: |
|
| 查看次数: |
13438 次 |
| 最近记录: |