I have a simple self referencing table as depicted here:
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] FO开发者_Go百科REIGN KEY([ParentProjectId])
REFERENCES [dbo].[Project] ([ProjectId])
I am trying to get a stored proc that will output the records in a tree view type way with a generated field that will index the level of each of the items like a table of contents like so:
1.0 parent
1.1 1st child
1.2 2nd child
1.2.1 1st grandchild of 2nd child
i have this proc that returns lvl but that's a flat representation and i want a field such as the numbers displayed above (1.1.1, 1.2 and so on)
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
Here's a version that may help
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
You'll find an additional CTE (before your original CTE) that derives a row number value for each group of ParentProjectId values. The row number is used as the numeric ID element.
精彩评论