您也可以使用纯SQL解决方案;这里是SQL Server的示例。对于不同的数据库管理器,重写它并不困难:
CREATE TABLE dbo.Nodes (ID int NOT NULL PRIMARY KEY, Parent int)
INSERT INTO Nodes VALUES (1,NULL)
INSERT INTO Nodes VALUES (2,1)
INSERT INTO Nodes VALUES (3,2)
INSERT INTO Nodes VALUES (4,3)
INSERT INTO Nodes VALUES (5,NULL)
INSERT INTO Nodes VALUES (6,5)
CREATE function dbo.fn_Root(@ID int) returns int
AS BEGIN
DECLARE @R int
SELECT @R = CASE WHEN Parent IS NULL THEN ID
ELSE dbo.fn_Root(Parent)
END
FROM Nodes
WHERE id = @id
RETURN @R
END
SELECT ID, Parent, dbo.fn_Root(ID) AS Root
FROM Nodes
ALTER TABLE Nodes ADD Root AS dbo.fn_Root(id)
这是基本版本。但如果您的数据有闭环(不是树形结构),这个版本将失败。为了防止代码进入无限循环,可以对函数进行改进,如下:
CREATE function dbo.fn_Root(@ID int, @Initial int) returns int
AS BEGIN
DECLARE @R int
DECLARE @Parent int
SELECT @Parent = Parent FROM Nodes WHERE ID = @ID
IF @Parent IS NULL
SELECT @R = @ID
ELSE
IF @Parent = @Initial
SELECT @R = NULL
ELSE
SELECT @R = dbo.fn_Root(@Parent,@Initial)
RETURN @R
END
SELECT ID, Parent, dbo.fn_Root(ID,ID) AS Root FROM Nodes
通过这个修改,如果函数返回NULL,则表示该节点是循环的一部分,因此它没有根节点。
null
,要么指向另一个“行”。 - Filip EkbergIEnumerable
,其中包含IEnumerable<int>
,其中每个IEnumerable<int>
表示父级下面的子级。 - Filip Ekberg