我需要通过排序、分区和分组进行行编号。订购依据IdDocument, DateChange
, 划分为IdDocument
并分组依据IdRole
。问题尤其出在分组上。从例子中可以看出(NumberingExpected
) DENSE_RANK()
必须是用于此目的的最佳函数,但仅当用于排序的值相同时才会重复编号。就我而言,用于排序的值(IdDocument, DateChange
)总是不同的,重复编号必须通过IdRole
.
当然,使用光标可以很容易地解决这个问题。但是有没有办法用编号/排名功能来实现呢?
测试数据:
declare @LogTest as table (
Id INT
,IdRole INT
,DateChange DATETIME
,IdDocument INT
,NumberingExpected INT
)
insert into @LogTest
select 1 as Id, 7 as IdRole, GETDATE() as DateChange, 13 as IdDocument, 1 as NumberingExpected
union
select 2, 3, DATEADD(HH, 1, GETDATE()), 13, 2
union
select 3, 3, DATEADD(HH, 2, GETDATE()), 13, 2
union
select 4, 3, DATEADD(HH, 3, GETDATE()), 13, 2
union
select 5, 5, DATEADD(HH, 4, GETDATE()), 13, 3
union
select 7, 3, DATEADD(HH, 6, GETDATE()), 13, 4
union
select 6, 3, DATEADD(HH, 5, GETDATE()), 27, 1
union
select 8, 3, DATEADD(HH, 7, GETDATE()), 27, 1
union
select 9, 5, DATEADD(HH, 8, GETDATE()), 27, 2
union
select 10, 3, DATEADD(HH, 9, GETDATE()), 27, 3
select * from @LogTest order by IdDocument, DateChange;
从函数式编程的角度解释:
- 按 IdDocument、DateChange 排序数据
- 将第一行号设置为 i=1 转到下一行
- 如果 IdDocument 已更改
{ 我=1; }
别的 {
如果 IdRow 已更改 { i++; }
}
- 设置行号为i;
- 转到下一行;
- 如果 EOF { 退出; } else { 转到步骤 3; }