需要递归的sql函数

时间:2010-10-04 19:39:12

标签: sql-server-2005

我有一个简单的自引用表,如下所示:

CREATE TABLE [dbo].[Project](
    [ProjectId] [int] NOT NULL,
    [ProjectName] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [ParentProjectId] [int] NULL
 CONSTRAINT [PK_Project] PRIMARY KEY CLUSTERED 
(
    [ProjectId] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

GO
ALTER TABLE [dbo].[Project]  WITH CHECK
ADD  CONSTRAINT [FK_Project_Project] FOREIGN KEY([ParentProjectId])
REFERENCES [dbo].[Project] ([ProjectId])

我正在尝试获取一个存储过程,该过程将以树视图类型的方式输出记录,其中生成的字段将索引每个项目的级别,如内容,如下所示:

1.0       parent
1.1       1st child
1.2       2nd child
1.2.1    1st grandchild of 2nd child

我有这个proc返回lvl,但这是一个平面表示,我想要一个字段,如上面显示的数字(1.1.1,1.2等)

CREATE PROCEDURE [dbo].[rpt_ExpandProjectList_stefano]    
( @ProjectId int = null)    
AS    
BEGIN    
WITH ProjectList(ProjectId, ParentProjectId, ProjectName,
                 ParentPath, Fullpath, Level)  
AS  
(  
-- Anchor member definition  
    SELECT p.ProjectId, p.ParentProjectId, p.ProjectName, CONVERT(nvarchar(1000), ''), CONVERT(nvarchar(1000), p.ProjectName) AS FullPath, 0 AS Level  
    FROM Project AS p     
    WHERE p.ProjectId = @ProjectId  
    UNION ALL  
-- Recursive member definition  
    SELECT p.ProjectId, p.ParentProjectId, p.ProjectName, CONVERT(nvarchar(1000), d.FullPath), CONVERT(nvarchar(1000), d.FullPath + '|' + p.ProjectName) as FullPath, Level + 1  
    FROM Project AS p  
    INNER JOIN ProjectList AS d  
       ON p.ParentProjectId = d.ProjectId  
)  
-- Statement that executes the CTE  
SELECT pl.ProjectId, pl.ParentProjectId, pl.ProjectName, pl.ParentPath, pl.FullPath, pl.Level  
FROM ProjectList pl  
ORDER BY pl.FullPath  
END

1 个答案:

答案 0 :(得分:0)

这是一个可能有用的版本

CREATE PROCEDURE [dbo].[rpt_ExpandProjectList_stefano]    
( @ProjectId int = null)    
AS    
BEGIN    

WITH ProjectNode (ProjectId, ParentProjectId, ProjectName, ProjectNode)
AS
(
-- Derive project node ID
    SELECT ProjectId, ParentProjectId, ProjectName,
        CAST(ROW_NUMBER() OVER (PARTITION BY ParentProjectId ORDER BY ProjectId) AS VARCHAR) AS ProjectNode
    FROM Project
),

    ProjectList(ProjectId, ParentProjectId, ProjectName,
                 ParentPath, Fullpath, Level, FullNodePath)  
AS  
(
-- Anchor member definition  
    SELECT p.ProjectId, p.ParentProjectId, p.ProjectName, CONVERT(nvarchar(1000), ''), 
        CONVERT(nvarchar(1000), p.ProjectName) AS FullPath, 0 AS Level,
        CONVERT(nvarchar(1000), p.ProjectNode) AS FullNodePath
    FROM ProjectNode AS p     
    WHERE p.ProjectId = @ProjectId  
    UNION ALL  
-- Recursive member definition  
    SELECT p.ProjectId, p.ParentProjectId, p.ProjectName, CONVERT(nvarchar(1000), d.FullPath), 
        CONVERT(nvarchar(1000), d.FullPath + '|' + p.ProjectName) as FullPath, Level + 1,
        CONVERT(nvarchar(1000), d.FullNodePath + '.' + p.ProjectNode) AS FullNodePath       
    FROM ProjectNode AS p  
    INNER JOIN ProjectList AS d  
       ON p.ParentProjectId = d.ProjectId  
)

-- Statement that executes the CTE  
SELECT pl.ProjectId, pl.ParentProjectId, pl.ProjectName, pl.ParentPath, pl.FullPath, pl.Level, pl.FullNodePath
FROM ProjectList pl  
ORDER BY pl.FullPath  
END

您将找到一个额外的CTE(在您的原始CTE之前),它为每组ParentProjectId值派生一个行号值。行号用作数字ID元素。