【SQL】根据当前ID查询到其顶层父级的ID


在一个表中,有这样的一个层级关系,ID为主键,PId为父级ID

关系如下图:

然后呢,现在的需求是,已知某一条记录的ID,求出它顶层父级的ID,也就是我们所谓的“寻根”计划。

这类问题解决方法很多,首先我用SQL中的函数来解决,许久不写,正好练习一下:

 1 --创建函数
 2  CREATE   function  F_FindPIdByID
 3 (  
 4    @ID varchar(15) --参数
 5 )
 6 returns varchar(500)
 7 as
 8 begin
 9 
10 declare @PId varchar(15) --变量父级ID,当前ID的PID
11 declare @Place varchar(500)    --变量Place,最终返回结果
12 set  @Place = '0' 
13 begin
14 --首先根据传入的ID获取其父ID,PID
15  SELECT    @PId = PId  FROM T_Recursion 
16     where  ID = @ID   
17 end
18 
19  if (@PId<> '0')--如果不是根节点
20     begin            
21         -- 再将@PID 作为参数@ID传入函数进行自调用        
22         set @Place =dbo.F_FindPIdByID(@PId);        
23     end
24  else
25     begin 
26         --满足PId=0这个条件,则把当前传入函数中的ID赋值并返回,即当前的PId就是最终要获取到的ID           
27         set @Place =@ID
28     end
29 return  @Place
30 end
31 go

函数创建好了(有点递归的味道)

 

下面给定参数,然后执行函数,看看结果

1 --测试A
2 select dbo.F_FindPIdByID(1111) as 'ID'
3 
4 --测试B
5 select dbo.F_FindPIdByID(21) as 'ID'
6 
7 --测试C
8 select dbo.F_FindPIdByID(31) as 'ID'

测试的结果

 

大功告成。

接下来,我们试试另一个方法。直接写查询语句来实现,这里要用到[ WITH AS ]。

什么是WITH AS?

1、WITH AS短语,也叫做子查询部分(subquery factoring),可以定义一个SQL片断,该SQL片断会被整个SQL语句用到。可以使SQL语句的可读性更高,也可以在UNION ALL的不同部分,作为提供数据的部分。

2、对于UNION ALL,使用WITH AS定义了一个UNION ALL语句,当该片断被调用2次以上,优化器会自动将该WITH AS短语所获取的数据放入一个Temp表中。而提示meterialize则是强制将WITH AS短语的数据放入一个全局临时表中。很多查询通过该方式都可以提高速度。

搞清楚什么是 with as,我们就来用一下,核心思想是ID作为PId条件找到上级ID

1 with Tree  AS
2 (
3     SELECT * FROM T_Recursion WHERE ID = 1111
4     UNION ALL
5     SELECT a.* FROM Tree , T_Recursion as a WHERE Tree.PId = a.ID
6 )
7 SELECT * FROM Tree order by ID ASC;

执行一下,我们发现结果是所有与之相关的记录:

,目的达到,完结撒花...

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM