Probeer dit:
;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
- De eerste CTE krijgt de verschillen met behulp van de
lag
functie (beschikbaar vanaf SQL Server 2012). - De volgende CTE berekent wanneer het verschil groter is dan 1 en wijst alle records daarna toe aan een 'groep', totdat het volgende verschil <> 1 wordt gevonden. Dit is de belangrijkste stap bij het groeperen.
- De laatste stap is het gebruik van
dense_rank
over de indicator berekend in de vorige stap om de rijnummers te krijgen zoals vereist.
Deze oplossing heeft wel een beperking in die zin dat het zal mislukken als de verschillen niet in oplopende volgorde zijn, d.w.z. als u nog twee waarden in de voorbeeldgegevens hebt, zoals 52 en 53, zal het deze in groep 3 classificeren in plaats van een nieuwe groep te maken.
Bijwerken :De onderstaande aanpak kan de bovenstaande beperking overwinnen:
;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
Ook hier blijft de eerste stap hetzelfde. Maar in stap 2 controleren we alleen op overgang naar een andere waarde van het verschil tussen opeenvolgende waarden, in plaats van een min/max-functie te gebruiken. De rangschikking gebruikt vervolgens een voorwaardelijke som om een groep toe te wijzen voor elke waarde in de oorspronkelijke gegevens.
Dit kan verder worden vereenvoudigd tot:
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