Sql 比递归cte性能更好的查询

Sql 比递归cte性能更好的查询,sql,sql-server,sql-server-2012,Sql,Sql Server,Sql Server 2012,我有大约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.

我有大约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)
; 
我们使用递归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的销售额。i、 e是1000。 除了递归cte之外,还有其他方法可以实现结果吗?请帮忙。

这里有一种使用数据类型的方法

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()
注:

层次结构\u No必须是数字,如示例中所示。将非数字字符转换为只能处理一个非数字字符。 没有其他列标识最后两个层次结构不同。因此,它们被分组到输出中。如果您有这样一列,请在GROUPBY语句中列出它
这里有一种方法仍然使用递归cte,但由于您没有共享您的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

此解决方案将每个层次结构转换为每个字符的行,以获得所需的层次结构:

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)<>'.'

取决于-层次结构始终基于3个级别,并假定为尾部。不相关吗?不,它可以超过3。最多我会有10个级别。谢谢1-1. 不在您的样本数据中,您如何选择它?您能否显示您现在拥有的递归cte,以便我们能够与之进行比较?@HoneyBadger这是我的样本数据,提供的数据是针对一个特定时期的