2010-10-04 62 views
0

我有一個簡單的自我引用表所描繪的位置:遞歸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 

回答

0

下面是得出每個組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