CREATE TABLE [dbo].[Nodes](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Data] [nvarchar](50) NOT NULL,
[ParentId] [int] NULL,
[Position] [char](1) NULL,
CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED (
[Id] ASC)
)
CREATE TABLE [dbo].[Closure](
[ParentId] [int] NOT NULL,
[ChildId] [int] NOT NULL,
[PathLength] [int] NOT NULL,
CONSTRAINT [PK_Closure] PRIMARY KEY CLUSTERED(
[ParentId] ASC,
[ChildId] ASC )
)
我需要做的是为特定节点获取极右节点。
有关查询的任何帮助以解决此问题?感谢。
答案 0 :(得分:0)
<强>的假设强>
Nodes.Position
确定父节点下子节点的位置,父节点是唯一的,而不是全局的。Nodes.Position
的值不是硬编码的,事先不知道。Nodes.Position
排序,则第一项是左项,最后一项是右项。<强>解强>
解决方案仅使用dbo.Nodes
,因为我无法找到一个解决方案,其中使用闭包表更容易遍历树深度优先级,并且在您的方案中,重要的Position
列已启用dbo.Nodes
。您可以从dbo.Closure
获取父级和子级ID,然后加入dbo.Nodes
以获取Position
,但这只会添加一些不必要的联接。
下面的查询是针对最右边的节点,要找到左边的节点,将排序更改为ASC
。
;WITH
RecCTE AS
(
SELECT
Id,
1 AS NodeLevel
FROM
(
SELECT
N.Id,
ROW_NUMBER() OVER (PARTITION BY N.ParentId ORDER BY N.Position DESC) AS NodeRank
FROM
dbo.Nodes AS N
WHERE
N.ParentId = @Parent
) AS SQ
WHERE
NodeRank = 1
UNION ALL
SELECT
Id,
NodeLevel + 1 AS NodeLevel
FROM
(
SELECT
N.Id,
R.NodeLevel,
ROW_NUMBER() OVER (PARTITION BY N.ParentId ORDER BY N.Position DESC) AS NodeRank
FROM
dbo.Nodes AS N
INNER JOIN RecCTE AS R ON N.ParentId = R.Id
) AS SQ
WHERE
NodeRank = 1
)
SELECT
Id
FROM
RecCTE
WHERE
NodeLevel IN ( SELECT MAX(NodeLevel) FROM RecCTE )
更新:嵌套设置解决方案
如果您对更改表结构持开放态度,我建议您查看此方案的嵌套集方法。例如,如果您有此表(填充节点位置):
CREATE TABLE [dbo].NestedSets
(
Id int NOT NULL PRIMARY KEY CLUSTERED,
LeftNum int NOT NULL,
RightNum int NOT NULL,
PathLength int NOT NULL
)
然后找到你的极左节点应该像
一样简单SELECT
C.Id
FROM
dbo.NestedSets AS C
INNER JOIN dbo.NestedSets AS P
ON P.LeftNum < C.LeftNum AND P.RightNum > C.RightNum
WHERE
P.Id = @Parent
AND C.LeftNum = C.RightNum - 1
AND C.LeftNum = P.LeftNum + C.PathLength - P.PathLength
最右边的节点:
SELECT
C.Id
FROM
dbo.NestedSets AS C
INNER JOIN dbo.NestedSets AS P
ON P.LeftNum < C.LeftNum AND P.RightNum > C.RightNum
WHERE
P.Id = @Parent
AND C.LeftNum = C.RightNum - 1
AND C.RightNum = P.RightNum - (C.PathLength - P.PathLength)
我不确定你的上下文闭包方法是否比嵌套集更有意义,但是为了这个查询的目的,差异非常大。