Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

criar partição com base na diferença entre os índices de linha subsequentes no sql server 2012


Tente isto:
    ;with cte as
    (select *, 
     coalesce(row_index - (lag(row_index) over (order by event)),1) diff
     from tbl
    ),

    cte2 as
    (select *, 
     (select max(diff) 
      from cte c 
      where c.row_index <= d.row_index
      ) minri
     from cte d
     )

    select event, row_index, minri, 
    dense_rank() over (order by minri) rn 
    from cte2
  • O primeiro CTE obtém as diferenças usando o lag função (disponível a partir do SQL Server 2012).
  • O próximo CTE calcula quando a diferença excede 1 e atribui todos os registros após esse ponto a um 'grupo', até que a próxima diferença <> 1 seja encontrada. Esta é a etapa chave no agrupamento.
  • A última etapa é usar dense_rank sobre o indicador calculado na etapa anterior para obter os números de linha conforme necessário.

Esta solução tem uma limitação na medida em que falhará se as diferenças não estiverem em ordem crescente, ou seja, se você tiver mais dois valores nos dados de amostra, como 52 e 53, ele os classificará no grupo 3 em vez de criar um novo grupo.

Demonstração

Atualizar :A abordagem abaixo pode superar a limitação acima:
    ;with cte as
    (select *, 
     coalesce(row_index - (lag(row_index) over (order by event)),1) diff
     from tbl)
    ,cte2 as
    (select *,
     diff - coalesce(diff - (lag(diff) over (order by event)),0) tmp
     from cte d)

     select event,row_index, 
     1 + sum(case when tmp >= diff then 0 else 1 end) over (order by event) risum
     from cte2

Novamente, o primeiro passo permanece o mesmo. Mas na etapa 2, verificamos apenas a transição para um valor diferente da diferença entre valores sucessivos, em vez de usar uma função min/max. A classificação usa uma soma condicional para atribuir um grupo para cada valor nos dados originais.

Demonstração

Isso pode ser ainda mais simplificado para:
select event, row_index, 
sum(case when diff <= 1 then 0 else 1 end) over (order by event) as rb
from
(select *, 
 row_index - (lag(row_index) over (order by event)) diff
 from tbl
) s