Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

creare la partizione in base alla differenza tra gli indici di riga successivi in ​​sql server 2012

Prova questo:

    ;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
  • Il primo CTE ottiene le differenze utilizzando il lag funzione (disponibile da SQL Server 2012 in poi).
  • Il CTE successivo calcola quando la differenza supera 1 e assegna tutti i record dopo quel punto a un 'gruppo', finché non viene trovata la differenza successiva <> 1. Questo è il passaggio chiave nel raggruppamento.
  • L'ultimo passaggio consiste nell'usare dense_rank sopra l'indicatore calcolato nel passaggio precedente per ottenere i numeri di riga richiesti.

Questa soluzione ha una limitazione in quanto fallirà se le differenze non sono in ordine crescente, ad esempio se hai altri due valori nei dati di esempio come 52 e 53, li classificherà nel gruppo 3 invece di creare un nuovo gruppo.

Demo

Aggiorna :L'approccio seguente può superare la limitazione di cui sopra:

    ;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

Anche in questo caso il primo passaggio rimane lo stesso. Ma nel passaggio 2, controlliamo solo la transizione a un valore diverso della differenza tra valori successivi, invece di utilizzare una funzione min/max. La classifica utilizza quindi una somma condizionale per assegnare un gruppo per ogni valore nei dati originali.

Demo

Questo può essere ulteriormente semplificato in:

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