如何在sql server中生成分层数据的序列号

时间:2015-02-12 12:23:57

标签: sql-server hierarchy hierarchical-data

我在sql中创建了一个函数来获取层次结构中的序列号。我有一个名为Goals的表。表的结构如下

 GoalId      ParentId   Goalstatement
----------   ----------  ----------
1               0          abc
2               0          def
3               1          acc
4               2          efc
5               3          dec
6               0          efc
7               3          jhg

我想写一个函数来得到结果

Serial no       GoalId           ParentId        GoalStatement
----------       ----------       ----------     --------------------
1                1                 0              
2                2                 0
3                6                 0
1.1              3                 1
1.1.1            5                 3
1.1.2            7                 3
2.1              4                 2

----------

我尝试过使用公用表表达式

WITH Hierarchy(GoalID, ParentId, Parents)
AS
(
    SELECT GoalID,  GoalParentID, CAST('' AS VARCHAR(MAX))
        FROM Goals AS FirtGeneration
        WHERE GoalParentID =0    
    UNION ALL
    SELECT NextGeneration.GoalID, NextGeneration.GoalParentID, 
    CAST(CASE WHEN Parent.Parents = ''
        THEN(CAST(NextGeneration.GoalParentID AS VARCHAR(MAX)))
        ELSE(Parent.Parents + '.' + CAST(NextGeneration.GoalParentID AS VARCHAR(MAX)))
    END AS VARCHAR(MAX))
        FROM Goals AS NextGeneration
        INNER JOIN Hierarchy AS Parent ON NextGeneration.GoalParentID = Parent.GoalID    
)
SELECT * 
    FROM Hierarchy 
OPTION(MAXRECURSION 32767)

任何人都可以帮我编写一个以分层方式创建序列号的函数

2 个答案:

答案 0 :(得分:3)

您的递归CTE非常接近,但您需要添加ROW_NUMBER()以便在层次结构的每个级别生成序列号。试试这个;

DECLARE @Goals TABLE (GoalId INT, GoalParentID INT, Goalstatement VARCHAR(100))

INSERT @Goals VALUES 
(1, 0, 'abc'),
(2, 0, 'def'),
(3, 1, 'acc'),
(4, 2, 'efc'),
(5, 3, 'dec'),
(6, 0, 'efc'),
(7, 3, 'jhg')

;WITH NumberedGoals(GoalId, GoalParentID, Goalstatement, GoalSequence) AS (
    SELECT
        GoalId, GoalParentID, Goalstatement, ROW_NUMBER() OVER (PARTITION BY GoalParentID ORDER BY GoalId) AS GoalSequence
    FROM
        @Goals
), Hierarchy(GoalID, GoalParentID, GoalSequence, Parents)
AS
(
    SELECT GoalID, GoalParentID, GoalSequence, CAST(GoalSequence AS VARCHAR(MAX))
        FROM NumberedGoals AS FirtGeneration
        WHERE GoalParentID = 0    
    UNION ALL
    SELECT NextGeneration.GoalID, NextGeneration.GoalParentID, NextGeneration.GoalSequence,
        CAST(CASE WHEN Parent.Parents = ''
            THEN(CAST(NextGeneration.GoalSequence AS VARCHAR(MAX)))
            ELSE(Parent.Parents + '.' + CAST(NextGeneration.GoalSequence AS VARCHAR(MAX)))
        END AS VARCHAR(MAX))
        FROM NumberedGoals AS NextGeneration
        INNER JOIN Hierarchy AS Parent ON NextGeneration.GoalParentID = Parent.GoalID    
)
SELECT h.Parents as [Serial no], h.GoalId, h.GoalParentId, g.GoalStatement
    FROM Hierarchy h
    JOIN @Goals g ON g.GoalID = h.GoalID
OPTION (MAXRECURSION 32767)

答案 1 :(得分:-1)

;with Hierarchy
as
(
    select GoalID, 
           ParentId,
           Row_Number() over(partition by ParentId order by GoalID) as number, 
           cast(Row_Number() over(partition by ParentId order by GoalID) as nvarchar(200)) newnumber
    from Goals where ParentId = 0
    Union All
      Select p.GoalId,
             p.ParentId,
            Row_Number() over(partition by p.ParentId order by p.GoalID) as number,
            cast(cte.newnumber + '.' + cast(Row_Number() over(partition by p.ParentId order by p.GoalID) as nvarchar(200)) as nvarchar(200)) newnumber
      From Goals p
      Join Hierarchy cte On cte.GoalId = p.ParentId
)

select * from Hierarchy