我只是想了解CTE和递归来解决我之前使用游标的问题。
create table ##ACC (
AccNo int,
Property char
)
Insert into ##ACC
VALUES (1,'A'),(1,'B'),(2,'A'),(2,'C'),(3,'C'),(4,'D')
我想要获得的是获得所有AccNo的列表,以及所有与通过Property相关的AccNo。所以我的预期结果是
PrimaryAccNo | LinkedAccNo
1 | 1
1 | 2
1 | 3
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2
3 | 3
4 | 4
我尝试了以下代码和变体,但我得到4个结果(PrimaryAccNo = LinkedAccNo),或者我达到了100次递归。
WITH Groups(PrimaryAccNo, LinkedAccNo)
AS
(
Select distinct AccNo, AccNo from ##ACC
UNION ALL
Select g.PrimaryAccNo, p.AccNo from
##ACC p inner join Groups g on p.AccNo=g.LinkedAccNo
inner join ##ACC pp on p.Property=pp.Property
where p.AccNo<> pp.AccNo
)
Select PrimaryAccNo,LinkedAccNo
from Groups
我做错了什么?
答案 0 :(得分:0)
您正在进入由数据中的周期引起的无限循环,例如:1&gt; 2&gt; 3> 2&gt; ......解决方案是跟踪已经消费的行#34;由于CTE的限制,这必须通过在每个CTE行中包括历史记录来完成,例如,通过组装后面的路径到达每一行。您可以取消评估最终, Path
上的select
,看看发生了什么。
-- Sample data.
declare @ACC as Table ( AccNo Int, Property Char );
insert into @ACC values
( 1, 'A' ), ( 1, 'B' ), ( 2, 'A' ), ( 2, 'C' ), ( 3, 'C' ), ( 4, 'D' );
select * from @ACC;
-- Recursive CTE.
with Groups as (
select distinct AccNo, AccNo as LinkedAccNo,
Cast( '|' + Cast( AccNo as VarChar(10) ) + '|' as VarChar(1024) ) as Path
from @ACC
union all
select G.AccNo, A.AccNo, Cast( Path + Cast( A.AccNo as VarChar(10) ) + '|' as VarChar(1024) )
from Groups as G inner join -- Take the latest round of new rows ...
@ACC as AP on AP.AccNo = G.LinkedAccNo inner join -- ... and get the Property for each ...
@ACC as A on A.Property = AP.Property -- ... to find new linked rows.
where G.Path not like '%|' + Cast( A.AccNo as VarChar(10) ) + '|%' )
select AccNo, LinkedAccNo -- , Path
from Groups
order by AccNo, LinkedAccNo;