sql >> Base de Datos >  >> RDS >> Sqlserver

crear una partición basada en la diferencia entre los índices de fila posteriores en el servidor sql 2012

Prueba esto:

    ;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
  • El primer CTE obtiene las diferencias usando el lag función (disponible desde SQL Server 2012 en adelante).
  • El siguiente CTE calcula cuando la diferencia excede 1 y asigna todos los registros después de ese punto a un 'grupo', hasta que se encuentra la siguiente diferencia <> 1. Este es el paso clave en la agrupación.
  • El último paso es usar dense_rank sobre el indicador calculado en el paso anterior para obtener los números de fila requeridos.

Esta solución tiene una limitación porque fallará si las diferencias no están en orden creciente, es decir, si tiene dos valores más en los datos de muestra, como 52 y 53, los clasificará en el grupo 3 en lugar de crear un nuevo grupo.

Demostración

Actualizar :El siguiente enfoque puede superar la limitación anterior:

    ;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

Una vez más, el primer paso sigue siendo el mismo. Pero en el paso 2, solo verificamos la transición a un valor diferente de la diferencia entre valores sucesivos, en lugar de usar una función min/max. Luego, la clasificación usa una suma condicional para asignar un grupo para cada valor en los datos originales.

Demostración

Esto se puede simplificar aún más a:

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