如何通过递归CTE或其他方法获取ID变更链的最终覆盖ID?
解决SQL Server中获取ID变更链最终ID的问题
这问题用递归CTE来处理简直完美,正好能顺着ID的替换链一路追到最终的那个ID。先给你理清楚整个流程,再上代码~
首先先确认一下我们的表结构和初始化数据:
CREATE TABLE [dbo].[IdChanges]( [ReplacedId] [int] NOT NULL, [OverrideId] [int] NOT NULL ); INSERT INTO dbo.IdChanges(ReplacedId,OverrideId)VALUES(17,18); INSERT INTO dbo.IdChanges(ReplacedId,OverrideId)VALUES(18,19); INSERT INTO dbo.IdChanges(ReplacedId,OverrideId)VALUES(19,20); INSERT INTO dbo.IdChanges(ReplacedId,OverrideId)VALUES(12,13); INSERT INTO dbo.IdChanges(ReplacedId,OverrideId)VALUES(13,14); CREATE TABLE [dbo].[IdActivity]( [Id] [int] NOT NULL, [IsActive] [bit] NOT NULL ); INSERT INTO dbo.IdActivity(Id,IsActive)VALUES(14,1); INSERT INTO dbo.IdActivity(Id,IsActive)VALUES(20,1); INSERT INTO dbo.IdActivity(Id,IsActive)VALUES(17,0); INSERT INTO dbo.IdActivity(Id,IsActive)VALUES(18,0); INSERT INTO dbo.IdActivity(Id,IsActive)VALUES(19,0); INSERT INTO dbo.IdActivity(Id,IsActive)VALUES(12,0); INSERT INTO dbo.IdActivity(Id,IsActive)VALUES(13,0); GO
接下来就是核心的递归CTE代码,用来追踪每个ID的最终替换目标:
WITH IdChangeChain AS ( -- 锚点成员:先把所有初始的替换关系拉进来,当前的临时最终ID就是OverrideId SELECT ReplacedId, OverrideId AS CurrentOverrideId FROM dbo.IdChanges UNION ALL -- 递归成员:沿着替换链往下追,把当前的OverrideId作为新的ReplacedId,找到它的下一个替换ID SELECT ic.ReplacedId, icc.CurrentOverrideId FROM dbo.IdChanges ic INNER JOIN IdChangeChain icc ON ic.OverrideId = icc.ReplacedId ) -- 对每个ReplacedId取最大的CurrentOverrideId,也就是这条链的最终ID SELECT ReplacedId, MAX(CurrentOverrideId) AS LastOverrideId FROM IdChangeChain GROUP BY ReplacedId ORDER BY ReplacedId;
运行这段代码后,就能得到你想要的结果:
ReplacedId LastOverrideId 17 20 18 20 19 20 12 14 13 14
简单解释一下逻辑:递归CTE的锚点成员先建立初始的替换关系,然后递归成员会不断迭代,把每个ID的后续替换链都串联起来——比如17的链会被扩展成17→18,17→19,17→20;最后通过分组取最大值,就能直接拿到每个ReplacedId对应的最终OverrideId了。
内容的提问来源于stack exchange,提问作者mangood
相关产品推荐
相关产品推荐

