答案 0 :(得分:3)
这是使用递归CTE的一种方法:
WITH cte AS (
SELECT t1.ID, t1.Node, t1.Son, t1.Name, CONVERT(VARCHAR(MAX), t1.Node + ',') AS path
FROM yourTable t1
WHERE NOT EXISTS (SELECT 1 FROM yourTable t2 WHERE t1.Node = t2.Son)
UNION ALL
SELECT t1.ID, t1.Node, t1.Son, t1.Name, CONVERT(VARCHAR(MAX), path + ',' + t2.Son)
FROM yourTable t1
INNER JOIN cte t2
ON t1.Node = t2.Son
)
SELECT
ID,
Node AS [Original Node],
CASE WHEN CHARINDEX(',', path) = 0
THEN path
ELSE LEFT(path, CHARINDEX(',', path) - 1) END AS [New Node],
Name
FROM cte
ORDER BY ID;
说明:要了解其工作原理,在CTE上查看以下直接查询的输出可能会有所帮助:
SELECT *
FROM cte
ORDER BY ID;
希望很清楚,技巧是如何起作用的。我们从所有原始祖先开始递归地构建一条道路。递归CTE完成后,我们将得到一个表,每个节点都有一个完整的路径,可以一直返回到原始祖先。然后,我们只需要采用系列中的第一个术语即可找到该祖先。
答案 1 :(得分:1)
设法回答自己,但与上面提到的标签不完全一样。
Drop table if exists ##Nodes
CREATE TABLE ##Nodes
(
NodeID varchar(20) NOT NULL,
SonNodeID varchar(20) NULL,
[Name] varchar(20) NULL
)
enter code here
INSERT INTO ##Nodes (NodeID, SonNodeID, [Name]) VALUES ('A', 'C','First')
INSERT INTO ##Nodes (NodeID, SonNodeID, [Name]) VALUES ('B', NULL,'Second')
INSERT INTO ##Nodes (NodeID, SonNodeID, [Name]) VALUES ('C', 'D','Third')
INSERT INTO ##Nodes (NodeID, SonNodeID, [Name]) VALUES ('D', 'E','Fourth')
INSERT INTO ##Nodes (NodeID, SonNodeID, [Name]) VALUES ('E', NULL,'Fifth')
INSERT INTO ##Nodes (NodeID, SonNodeID, [Name]) VALUES ('F', 'I','Sixth')
INSERT INTO ##Nodes (NodeID, SonNodeID, [Name]) VALUES ('G', NULL,'Seventh')
INSERT INTO ##Nodes (NodeID, SonNodeID, [Name]) VALUES ('H', NULL,'Eighth')
INSERT INTO ##Nodes (NodeID, SonNodeID, [Name]) VALUES ('I', NULL,'Nineth')
WITH Nodes AS
(
--initialization
SELECT NodeID, SonNodeID, [Name], Father = NodeID , 1 AS GenerationsRemoved
FROM ##Nodes
UNION ALL
----recursive execution
SELECT N.NodeID, N.SonNodeID, P.[Name], Father = P.Father, P.GenerationsRemoved + 1
FROM Nodes AS P
INNER JOIN ##Nodes AS N
ON P.SonNodeID = N.NodeID
WHERE P.GenerationsRemoved <= 100
)
SELECT a.NodeID, AncientFather = Father, a.[Name]
FROM Nodes as a
join
(
Select NodeID, MaxGen = max(GenerationsRemoved)
from Nodes
group by NodeID
)as b on a.NodeID = b.NodeID
and a.GenerationsRemoved = b.MaxGen
ORDER BY a.NodeID
结果:
答案 2 :(得分:0)
我知道它并不完美,但是这种方法效果很好,可以提供您想要的结果:
select t1.ID, t1.NODE as ORIGINAL_NODE,
CASE
when t4.SON is not null then t4.NODE
when t3.SON is not null then t3.NODE
when t2.SON is not null then t2.NODE
else t1.NODE
END as NEW_NODE,
CASE
when t4.NAME is not null then t4.NAME
when t3.NAME is not null then t3.NAME
when t2.NAME is not null then t2.NAME
else t1.NAME
END as NAME
from Table t1
left outer join Table t2
on t1.NODE = t2.SON
left outer join Table t3
on t2.NODE = t3.SON
left outer join Table t4
on t3.NODE = t4.SON
order by t1.ID