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

créer une partition basée sur la différence entre les indices de ligne suivants dans sql server 2012

Essayez ceci :

    ;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
  • Le premier CTE obtient les différences en utilisant le lag fonction (disponible à partir de SQL Server 2012).
  • Le CTE suivant calcule lorsque la différence dépasse 1 et affecte tous les enregistrements après ce point à un « groupe », jusqu'à ce que la différence suivante <> 1 soit trouvée. C'est l'étape clé du regroupement.
  • La dernière étape consiste à utiliser dense_rank remplacer l'indicateur calculé à l'étape précédente pour obtenir les numéros de ligne nécessaires.

Cette solution a une limitation en ce sens qu'il échouera si les différences ne sont pas dans l'ordre croissant, c'est-à-dire si vous avez deux valeurs supplémentaires dans les données d'échantillon telles que 52 et 53, il les classera dans le groupe 3 au lieu de créer un nouveau groupe.

Démo

Mettre à jour  :L'approche ci-dessous peut surmonter la limitation ci-dessus :

    ;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

Encore une fois, la première étape reste la même. Mais à l'étape 2, nous vérifions uniquement la transition vers une valeur différente de la différence entre les valeurs successives, au lieu d'utiliser une fonction min/max. Le classement utilise ensuite une somme conditionnelle pour attribuer un groupe à chaque valeur des données d'origine.

Démo

Cela peut être simplifié davantage :

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