Hãy thử điều này:
;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
- CTE đầu tiên nhận được sự khác biệt bằng cách sử dụng
lag
chức năng (có sẵn từ SQL Server 2012 trở đi). - CTE tiếp theo sẽ tính toán khi sự khác biệt vượt quá 1 và gán tất cả các bản ghi sau điểm đó cho một 'nhóm', cho đến khi tìm thấy sự khác biệt tiếp theo <> 1. Đây là bước quan trọng trong việc phân nhóm.
- Bước cuối cùng là sử dụng
dense_rank
vượt chỉ số được tính toán ở bước trước để nhận được số hàng theo yêu cầu.
Giải pháp này có một hạn chế trong đó nó sẽ không thành công nếu sự khác biệt không theo thứ tự tăng dần, tức là nếu bạn có thêm hai giá trị trong dữ liệu mẫu, chẳng hạn như 52 và 53, nó sẽ phân loại chúng thành nhóm 3 thay vì tạo một nhóm mới.
Cập nhật :Cách tiếp cận dưới đây có thể khắc phục hạn chế trên:
;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
Một lần nữa bước đầu tiên vẫn như cũ. Nhưng trong bước 2, chúng tôi chỉ kiểm tra sự chuyển đổi sang một giá trị khác của sự khác biệt giữa các giá trị liên tiếp, thay vì sử dụng hàm min / max. Sau đó, xếp hạng sử dụng một tổng có điều kiện để chỉ định một nhóm cho mỗi giá trị trong dữ liệu gốc.
Điều này có thể được đơn giản hóa thêm thành:
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