Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

CTE récursif SQL :recherche d'objets liés par propriété

Vous rencontrez une boucle infinie causée par des cycles dans vos données, par exemple :1> 2> 3> 2> ... . La solution consiste à garder une trace des lignes qui ont déjà été "consommées". En raison des limitations des CTE, cela doit être fait en incluant l'historique dans chaque ligne CTE, par ex. en assemblant le chemin suivi pour arriver à chaque rangée. Vous pouvez décommenter le , Path sur le dernier select pour voir ce qui se passe.

-- 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;