EDITAR
Ao ler a documentação do CTE sobre recursão, você notará que ela tem alguns limites, como não poder usar subconsultas, group-by, top. Todos eles envolvem várias linhas. De testes limitados e verificando o plano de execução, além de testar essa consulta
with cte as (
select 1 a, 1 b union all select 1, 2 union all select 1, 3 union all select 2, 4
)
, rcte (a, b, c, d) as (
select a, b, cast(0 as int), 1
from cte
union all
select r.a, cte.b, cast(ROW_NUMBER() over (order by r.b) as int), r.d+1
from rcte r inner join cte on cte.a=r.a
where r.d < 2
)
select *
from rcte
where d=2
order by a, b
Só posso concluir:
- Row_Number() funciona em um CTE, quando outras tabelas são unidas para produzir um conjunto de resultados de várias linhas
- A partir dos resultados da numeração, fica claro que os CTEs são processados em uma única linha por todas as iterações, linha por linha em vez de multilinha por multilinha, mesmo que pareça iterar todas as linhas simultaneamente. Isso explicaria por que nenhuma das funções que se aplicam a operações de várias linhas não são permitidas para CTE recursiva.
Embora eu tenha chegado a essa conclusão facilmente, alguém obviamente levou muito mais tempo para explicar em detalhes excruciantes somente 17 meses atrás...
Em outras palavras, essa é a natureza da implementação do SQL Server do CTE recursiva, portanto, as funções de janela não funcionarão da maneira que você espera.
Para o benefício de outros, a saída é:
a b c d
----------- ----------- ----------- -----------
1 1 1 2
1 2 1 2
2 3 1 2
2 4 1 2
Considerando que você espera que c contenha 1,2,1,2 em vez de 1,1,1,1.
Observação:row_number() retorna bigint, então você pode converter apenas a âncora(c) como bigint.
Como cada iteração aumenta d, você pode executar a janela externa.
with cte as (
select 1 a, 1 b union all select 1, 2 union all select 2, 3 union all select 2, 4
)
, rcte (a, b, d) as (
select a, b, 1
from cte
union all
select a, b, d+1
from rcte
where d < 2
)
select a,b, ROW_NUMBER() over (partition by a,d order by b) c,d
from rcte
--where d=2
order by d, a, b
EDITAR - insight
Ao responder outra pergunta , joguei um pouco mais com CTE recursiva. Se você executá-lo sem o ORDER BY final, poderá ver como o SQL Server está se aproximando da recursão. É interessante que ele retroceda neste caso e, em seguida, faça uma recursão de profundidade total em cada linha.
Tabela de amostra
create table Testdata(SomeID int, OtherID int, Data varchar(max))
insert Testdata select 1, 9, '18,20,22,alpha,beta,gamma,delta'
insert Testdata select 2, 6, ''
insert Testdata select 3, 8, '11,12,.'
insert Testdata select 4, 7, '13,19,20,66,12,232,1232,12312,1312,abc,def'
insert Testdata select 5, 8, '17,19'
Uma consulta recursiva
;with tmp(SomeID, OtherID, DataItem, Data) as (
select SomeID, OtherID, LEFT(Data, CHARINDEX(',',Data+',')-1),
STUFF(Data, 1, CHARINDEX(',',Data+','), '')
from Testdata
union all
select SomeID, OtherID, LEFT(Data, CHARINDEX(',',Data+',')-1),
STUFF(Data, 1, CHARINDEX(',',Data+','), '')
from tmp
where Data > ''
)
select SomeID, OtherID, DataItem, Data
from tmp
-- order by SomeID
A saída mostra a âncora CTE processada na iteração um, então por qualquer motivo cada linha no conjunto âncora é recursiva até a conclusão (primeiro em profundidade) antes de processar outras linhas.
No entanto, tem seus usos estranhos, como esta resposta programas