我有大约500万条记录的数据,以下是与之相关的样本数据
if object_id('tempdb..#Table1') is not null
drop TABLE #Table1
CREATE TABLE #Table1
([Hierarchy_No] varchar(8), [sales] int)
;
INSERT INTO #Table1
([Hierarchy_No], [sales])
VALUES
('1-1.1.1.', 100),
('1-1.1.2.', 200),
('1-1.2.1', 300),
('1-1.2.1', 400),
('1-2.1.1.', 500),
('1-2.1.2.', 600),
('1-2.2.1', 700),
('1-2.2.1', 800)
;
我们使用recursive cte来实现以下结果。
Hierarchy_No sales
1-1. 1000
1-2. 2600
1-1.1. 300
1-1.2. 700
1-2.1. 1100
1-2.2. 1500
1-1.1.1. 100
1-1.1.2. 200
1-1.2.1 300
1-1.2.1 400
1-2.1.1. 500
1-2.1.2. 600
1-2.2.1. 700
1-2.2.1. 800
达到1-1的结果。我们必须增加1-1.1.1.+1-1.1.2.+1-1.2.1.+1-1-2.1.
的销售额,即1000。
有什么办法可以实现除递归cte之外的结果吗?请帮助。
答案 0 :(得分:2)
这是一种方法(仍然使用递归cte,但由于你没有分享你的,我不知道这是否会更好):
;WITH RCTE AS
(
SELECT [Hierarchy_No],
CHARINDEX('.', [Hierarchy_No]) As DotPosition,
[sales]
FROM #Table1
UNION ALL
SELECT [Hierarchy_No],
CHARINDEX('.', [Hierarchy_No], DotPosition + 1),
[sales]
FROM RCTE
WHERE DotPosition > 0 AND DotPosition < LEN([Hierarchy_No]) - 1
)
SELECT LEFT([Hierarchy_No], DotPosition) As Hierarchy, SUM([sales]) As Total_Sales
FROM RCTE
GROUP BY LEFT([Hierarchy_No], DotPosition)
我还尝试使用数字表而不是递归cte,但我的所有尝试都被证明对此示例数据的效果较差。
SELECT LEFT ([Hierarchy_No], Number) As Hierarchy,
SUM(sales)
FROM #Table1
INNER JOIN
(
SELECT Number
FROM Tally
WHERE Number <= 8 -- (the maximum length of the `[Hierarchy_No]` column)
)
Tally ON SUBSTRING([Hierarchy_No], Number, 1) = '.'
GROUP BY LEFT ([Hierarchy_No], Number)
ORDER BY Hierarchy
答案 1 :(得分:1)
这是使用hierarchyid数据类型
的单向方式select
stuff(replace(replace(res.GetAncestor(n).ToString(), '.', '-'), '/', '.'), 1, 1, '')
, sum(sales)
from (
select
*, res = cast('/' + replace(replace(Hierarchy_No, '.', '/'), '-', '.') as hierarchyid)
from
#Table1 c
join (values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9)) t(n)
on len(Hierarchy_No) - len(replace(Hierarchy_No, '.', '')) > t.n
) t
group by res.GetAncestor(n).ToString()
注意:
Hierarchy_No
必须是数字,如您的示例所示。通过将其转换为.
Hierarchy_No
不同。所以它们在输出中分组。如果您有这样的列答案 2 :(得分:0)
此解决方案将每个hierarchy_no转换为每个字符的行,以获得所需的层次结构:
select x.HierarchyCheck as [Hierarchy_No], sum(t1.sales) as [sales]
from #table1 t1
inner join (
SELECT distinct IIF(SUBSTRING([Hierarchy_No],Number,1) = '.', LEFT([Hierarchy_No], number), '') as HierarchyCheck
FROM #Table1
CROSS APPLY (SELECT DISTINCT number FROM master..spt_values WHERE number > 0 AND number <= LEN([Hierarchy_No]))V ) as x on t1.Hierarchy_No like x.HierarchyCheck + '%' and right(x.HierarchyCheck, 1) ='.'
group by x.HierarchyCheck
UNION
select T1.Hierarchy_No as [Hierarchy_No], t1.sales as [sales]
from #table1 t1
WHERE RIGHT(T1.Hierarchy_No,1)<>'.'