SQL Server 공용 표 표현 식(CTE)재 귀적 방법

공용 표 표현 식 개요:
공용 표 표현 식(CTE)은 하나의 SELECT,INSERT,UPDATE,DELETE 또는 CREATE VIEW 문장의 실행 범위 내 에서 정 의 된 임시 결과 집합 이 라 고 볼 수 있다.CTE 는 파생 표 와 유사 하 며 구체 적 으로 저장 되 지 않 은 대상 에 나타 나 며 조회 기간 에 만 유효 합 니 다.파생 표 와 다른 점 은 공용 표 표현 식(CTE)이 자신 을 인용 하여 재 귀 CTE 를 만 들 수 있다 는 중요 한 장점 을 가지 고 있다 는 점 이다.재 귀 CTE 는 전체 결과 집합 을 가 져 올 때 까지 초기 CTE 를 반복 적 으로 실행 하 는 공용 표 표현 식 입 니 다.
다음 에 먼저 표를 만 들 고 데 이 터 를 삽입 합 니 다.

create table Role_CTE
(
 Id  int    not null,
 Name nvarchar(32) not null,
 ParentId int  not null 
)
insert into Role_CTE(Id,Name,ParentId)
select '1','     ','0' union 
select '2','   A','1' union 
select '3','   B','2' union 
select '4','  AA','2' union 
select '5','  AB','2' union 
select '6','  BA','3' union 
select '7','  BB','3' union 
select '8','  AAA','4' union 
select '9','  BBA','7' 
--           
create clustered index Clu_Role_CTE_Index
on Role_CTE(Id,ParentId)
with
(
 pad_index=on,
 fillfactor=50,
 drop_existing=off,
 statistics_norecompute=on
)
select * from Role_CTE

지정 한 노드 의 모든 자손 노드 찾기:
일반 sql 문 구 를 사용 하여 구현:

declare @level int
declare @node int
declare @ResTab table
(
 node int not null,
 lv  int not null 
)
set @level=0  --        
set @node=3   --       ID,             
insert into @ResTab    --            
select Id,@level 
from Role_CTE 
where Id=@node
while(@@ROWCOUNT>0)
begin
 set @level=@level+1
 insert into @ResTab
 select b.Id,@level 
 from @ResTab a 
 join Role_CTE b on a.node=b.ParentId and lv=@level-1 -- join    inner join(   )    
end
select a.node,b.Name,a.lv 
from @ResTab a 
left join Role_CTE b on a.node=b.Id

이상 은 지 정 된 노드 ID(3)에 따라 부모 노드 ID(즉 필드 ParentId)가 지 정 된 노드 ID 와 같은 것 을 찾 고 있 으 면 삽입 하고 계속 순환 합 니 다.
PS:lv=@level-1가 중점 입 니 다.그렇지 않 으 면 사 순환 에 들 어 갈 수 있 습 니 다.역할 은 한 번 만 삽입 하 는 것 을 제한 하 는 것 입 니 다.
순환 횟수,즉 재 귀 층수 가 필요 하 다 면 while 조건 에 제한 을 추가 하면 된다.다음 과 같다.

declare @level int
declare @node int
declare @num int
declare @ResTab table
(
 node int not null,
 lv  int not null 
)
set @level=0  --        
set @node=3   --       ID,             
set @num=1  --       ,      
insert into @ResTab    --            
select Id,@level 
from Role_CTE 
where Id=@node
while(@@ROWCOUNT>0 and @level<@num)
begin
 set @level=@level+1
 insert into @ResTab
 select b.Id,@level 
 from @ResTab a 
 join Role_CTE b on a.node=b.ParentId and lv=@level-1 -- join    inner join(   )    
end
select a.node,b.Name,a.lv 
from @ResTab a 
left join Role_CTE b on a.node=b.Id

물론 순환 횟수 를 지정 하면 while 판단 문장의@rowcount>0 을 사용 하지 않 아 도 됩 니 다.
SQL CTE 를 사용 하여 구현:

declare @node int 
set @node=3;
with temp_cte
as
(
 select Id,Name,0 lv  --    “   ”,        
 from Role_CTE 
 where Id=@node 
 union all
 select b.Id,b.Name,a.lv+1 
 from temp_cte a 
 join Role_CTE b on a.Id=b.ParentId
)
select * from temp_cte

CTE 를 사용 하여 재 귀적 인 층 수 를 제어 합 니 다.위 와 유사 합 니 다.다음 과 같다.

declare @node int 
declare @num int
set @node=3;
set @num=1;
with temp_cte
as
(
 select Id,Name,0 lv  --    “   ”,        
 from Role_CTE 
 where Id=@node 
 union all
 select b.Id,b.Name,a.lv+1 
 from temp_cte a 
 join Role_CTE b on a.Id=b.ParentId
     and a.lv<@num  --      
)
select * from temp_cte

지정 한 노드 의 모든 조상 노드 찾기:
일반 sql 문 구 를 사용 하여 구현:

declare @level int
declare @node int
declare @num int
declare @ResTab table
(
 node int not null,
 lv  int not null 
)
set @level=0 --        
set @node=8   --       ID,             
set @num=2  --       ,      
while(@level<=@num and @node is not null) --               
begin
 insert into @ResTab
 select @node,@level
 set @level=@level+1
 select @node=ParentId 
 from Role_CTE 
 where Id=@node
end
select a.node,b.Name,a.lv 
from @ResTab a 
left join Role_CTE b on a.node=b.Id

SQL CTE 를 사용 하여 구현:

declare @node int 
declare @num int
set @node=8;
set @num=2;
with temp_cte
as
(
 select Id,Name,ParentId,0 lv  --    “   ”,        
 from Role_CTE 
 where Id=@node 
 union all
 select b.Id,b.Name,b.ParentId,a.lv+1 
 from temp_cte a 
 join Role_CTE b on a.ParentId=b.Id
     and a.lv < @num  --      
)
select * from temp_cte

위 에서 말 한 것 은 소 편 이 여러분 에 게 소개 한 SQL Server 공용 표 표현 식(CTE)을 재 귀적 으로 실현 하 는 방법 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 저 에 게 메 시 지 를 남 겨 주세요.소 편 은 제때에 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 지지 에 감 사 드 립 니 다!

좋은 웹페이지 즐겨찾기