递归SQL函数需要

问题描述:

我有一个简单的自我引用表所描绘的位置:递归SQL函数需要

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 

下面是得出每个组ParentProjectId值的行号值的版本,可以帮助

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之前)。行号被用作数字ID元素。

+0

因为这个表在我们运行SP时对projectID和ParentProjectID具有FK约束,所以它给出了“最大递归100已被耗尽”的错误! – Thakur 2010-10-04 21:01:56

+0

@Aamod Thakur - 数据中的最大值是多少?每个*项目是否有许多儿童,孙辈等项目?原始查询是否产生相同的错误? – bobs 2010-10-04 21:26:05

+0

是的,在我的情况下,我已经为根节点取了projectID = 1和ParentProjectID = 1。 – Thakur 2010-10-04 21:31:43