Estou tentando escrever um CTE recursivo para explorar um sistema de fluxo de trabalho. Infelizmente, estou recebendo erros máximos de recursão devido a loops:
with cteActs as
(
select a.id as [id], aa.TASKNEXTID as [childid]
from TASK a
inner join TASKNEXT aa on a.id = aa.TASKPARENTID
where a.id != aa.TASKNEXTID
),
cteNext as
(
select a.*
from cteActs as a
where a.id=42
union all
select a.*
from cteActs as a
inner join cteNext as n on a.id = n.childid
)
select *
from cteNext
A tabela TASK
é uma lista de tarefas em que 42 é "Iniciar trabalho", por exemplo. TASKNEXT
vincula 42 a possíveis subtarefas na TASK
tabela. por exemplo, pode ligar 42 a 43 que pode ser "Encontrar materiais", por exemplo
ID, name, childID
42, Start job, 43
42, Start job, 44
43, Find materials, 200
44, Report to boss, 201
201, Discuss with boss, 202
202, Receive payment, 44
Acho que a recursão está morrendo porque 44>201>202>44 cria um loop do qual a consulta não escapa. Como posso permitir isso? A maioria dos exemplos/tutoriais que li assumem um relacionamento estrito pai>filho, onde um filho nunca pode ser o pai de algo em sua própria árvore superior.
O que estou tentando obter é uma lista distinta TASKS
de fluxos que começam na tarefa 42, ou onde eu escolher.
Esta é a iteração 2 que pode funcionar, mas é tão lenta:
select a.id as [id], aa.ACTIONACTIVITYID as [childid]
into #temp
from TASK a
inner joinTASKNEXT aa on a.id = aa.TASKPARENTID
where a.id != aa.TASKNEXTID
create clustered index [hello] on #temp (ID ASC)
create nonclustered index [hello2] on #temp (childid ASC)
;
with cteNext as
(
select a.*,
cast(',' + cast(a.ID as varchar(10)) + ',' as varchar(max)) as Path,
0 as [cyc]
from #temp as a
where a.id=42
union all
select a.*,
n.Path + cast(a.ID as varchar(10)) + ',',
case when n.Path like '%,'+cast(a.ID as varchar(10))+',%'
then 1
else 0
end as [cyc]
from #temp as a
inner join cteNext as n on a.id = n.childid
where n.cyc = 0
)
select id, childid
from cteNext
where cyc =0
Portanto, o melhor resultado que consegui foi adicionar as seguintes melhorias
- otimizando a tabela consultada (criando uma nova tabela temporária com índices sugeridos)
- adicionando um elemento de caminho para verificar se não estou revisitando uma parte existente do caminho
- adicionar um contador de profundidade como limitador. No entanto, isso significa que estou escolhendo conscientemente não ter o conjunto de resultados completo
O objetivo inicial desses dados é "fofo", estou gerando um mapa de gráfico para mostrar nossos fluxos de trabalho para que uma profundidade limitada seja boa, pelo menos em primeira instância. Mas melhores respostas aceitas se alguém tiver alguma