排名:如何将ROW_NUMBER或RANK重置为1

All*_* Xu 1 sql t-sql sql-server ranking sql-server-2014

使用SQL Server 2014:

请考虑下表:

DECLARE @Table TABLE (
      Id int NOT NULL identity(1,1),
      Col_Value varchar(2)
)

INSERT INTO @Table (Col_Value)
VALUES ('A'),('A'),('B'),('B'),('B'),('A'),('A'),('B'),('B'),('B'),('A'),('B'),('B'),('A'),('A'),('B'),('C'),('C'),('A'),('A'),('B'),('B'),('C')
Run Code Online (Sandbox Code Playgroud)

如何在结果中创建一个生成R列的查询,如下所示

+----+------+---+
| ID | Data | R |
+----+------+---+
| 1  | A    | 1 |
+----+------+---+
| 2  | A    | 2 |
+----+------+---+
| 3  | B    | 1 |
+----+------+---+
| 4  | B    | 2 |
+----+------+---+
| 5  | B    | 3 |
+----+------+---+
| 6  | A    | 1 |
+----+------+---+
| 7  | A    | 2 |
+----+------+---+
| 8  | B    | 1 |
+----+------+---+
| 9  | B    | 2 |
+----+------+---+
| 10 | B    | 3 |
+----+------+---+
| 11 | A    | 1 |
+----+------+---+
| 12 | B    | 1 |
+----+------+---+
| 13 | B    | 2 |
+----+------+---+
| 14 | A    | 1 |
+----+------+---+
| 15 | A    | 2 |
+----+------+---+
| 16 | B    | 1 |
+----+------+---+
| 17 | C    | 1 |
+----+------+---+
| 18 | C    | 2 |
+----+------+---+
| 19 | A    | 1 |
+----+------+---+
| 20 | A    | 2 |
+----+------+---+
| 21 | B    | 1 |
+----+------+---+
| 22 | B    | 2 |
+----+------+---+
| 23 | C    | 1 |
+----+------+---+
Run Code Online (Sandbox Code Playgroud)

在上面的结果表中,一旦Data列连续变化,R值将重置为1

更新1

Ben Thul的答案非常有效.

我建议在帖子下面更新一下这个答案的参考.

T-sql重置字段更改时的行号

Ben*_*hul 6

这被称为文献中的"间隙和岛屿"问题.首先,我提出的解决方案:

with cte as (
    select *, [Id] - row_number() over (partition by [Col_Value] order by [Id]) as [GroupID]
    from @table
)
select [Id], [Col_Value], row_number() over (partition by [GroupID], [Col_Value] order by [Id])
from cte
order by [Id];
Run Code Online (Sandbox Code Playgroud)

对于说明,请注意,如果我使用枚举所有"A"值row_number(),那些连续的row_number()值的值将与Id值的速率相同.也就是说,他们的差异对于那个连续组(也称为"岛")的人来说是相同的.一旦我们计算了该组标识符,它就只是枚举每个组的每个成员.