递归 CTE 查找父记录

Posted

技术标签:

【中文标题】递归 CTE 查找父记录【英文标题】:Recursive CTE to find parent records 【发布时间】:2011-04-25 12:02:13 【问题描述】:

首先我必须承认我对sql server的recursive CTE's不是很熟悉,但我认为这是最好的方法。

我有一张桌子tabData。它的 PK 被命名为 idData,并且有一个自引用 FK fiData

所以 fiData 引用父记录,SELECT * FROM tabData WHERE idData=fiData 返回父记录的所有数据。这既简单又快速。但是如何按自然顺序从给定记录中获取所有父母? 假设有一个孩子(idData=4)有 3 个父母(第一个父母是 idData=3 的记录):

idData    fiData 
 4          3     
 3          2     
 2          1    
 1          NULL    

我认为递归 CTE 是要走的路,但我不能很好地理解它的语法。 那么实现返回所有父母的CTE的正确方法是什么?

我尝试了以下操作,但它给了我错误的结果(3,4 而不是 3,2,1): (为了测试它,我为我和你创建了一个临时表)

IF (NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND  TABLE_NAME = 'tabData_Temp'))
BEGIN
 CREATE TABLE [dbo].[tabData_Temp](
  [idData] [int] NOT NULL,
  [fiData] [int] NULL,
   CONSTRAINT [PK_tabData_Temp] PRIMARY KEY CLUSTERED 
  (
   [idData] ASC
  )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON)
 );

 ALTER TABLE [dbo].[tabData_Temp]  WITH CHECK ADD  CONSTRAINT [FK_tabData_Temp] FOREIGN KEY([fiData])
 REFERENCES [dbo].[tabData_Temp] ([idData]);
 ALTER TABLE [dbo].[tabData_Temp] CHECK CONSTRAINT [FK_tabData_Temp];

 INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(1,NULL);
 INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(2,1);
 INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(3,2);
 INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(4,3);
END

/* here comes the (not working) recursive CTE */
Declare @fiData int;
SET @fiData = 3;
WITH PreviousClaims(idData,fiData) 
AS(
     SELECT parent.idData,parent.fiData
     FROM tabData_temp parent
     WHERE parent.idData = @fiData

     UNION ALL

     SELECT child.idData,child.fiData
     FROM tabData_temp child
     INNER JOIN PreviousClaims parent ON parent.idData = child.fiData
)
SELECT idData
FROM PreviousClaims;
/* end of recursive CTE */


DROP TABLE [dbo].[tabData_Temp];

提前谢谢你。

【问题讨论】:

【参考方案1】:

改为:

INNER JOIN PreviousClaims parent ON parent.fiData = child.idData

给我你想要的结果。

【讨论】:

【参考方案2】:

你有向后的连接。

改变这个

INNER JOIN PreviousClaims parent ON parent.idData= child.fiData 

到这里

INNER JOIN PreviousClaims parent ON parent.fiData = child.idData

【讨论】:

谢谢,Kirk Woll 快了几秒。

以上是关于递归 CTE 查找父记录的主要内容,如果未能解决你的问题,请参考以下文章

递归 CTE 通过多个级别更新父记录

递归 CTE - 查找经理下的所有员工

递归 Cte 在 SQL 中查找 Min 和 Max 相关数据? [关闭]

使用MySQL 8.0递归CTE查找层次结构表中的直接后代并传播给父级

SQL SERVER 下:1递归查询父分类下的各个子分类。 2查询每个商品分类中最贵的前两个商品SQL

递归 CTE - row_number() 聚合