SQL 服务器中的组排名

Ranking by Groups in SQL SERVER


我需要按 'String' 和 'Is_sep' 对以下组进行排名,并按 'Id' 保持顺序: (SQL 服务器)
ID      | String    | Is_Sep    | Rank      | Rank_DESC
1       | XX        | 0         | 1         | 3
2       | XX        | 0         | 2         | 2
3       | XX        | 1         | 3         | 1
4       | XX        | 0         | 1         | 3
5       | XX        | 0         | 2         | 2
6       | XX        | 1         | 3         | 1
7       | YY        | 0         | 1         | 4
8       | YY        | 0         | 2         | 3
9       | YY        | 0         | 3         | 2
10      | YY        | 1         | 4         | 1
11      | ZZ        | 0         | 1         | 2
12      | ZZ        | 1         | 2         | 1
13      | ZZ        | 0         | 1         | 3
14      | ZZ        | 0         | 2         | 2
15      | ZZ        | 1         | 3         | 1

知道怎么做吗?

谢谢!

这是一种间隙和孤岛问题,其中 is_sep 标记每个孤岛的终点。

我会使用 window 总和来定义组,然后 row_number():

select 
    id,
    string,
    sep,
    row_number() over(partition by string, grp order by id) rn,
    row_number() over(partition by string, grp order by id desc) rn_desc
from (
    select 
        t.*,
        sum(is_sep) over(partition by string order by id desc) grp
    from mytable t
) t
order by id

请注意,对于此示例数据,分区中实际上不需要 string,因为 is_sep 还表示 string 值之间的转换。所以这同样有效:

select 
    id,
    string,
    is_sep,
    row_number() over(partition by grp order by id) rn,
    row_number() over(partition by grp order by id desc) rn_desc
from (
    select 
        t.*,
        sum(is_sep) over(order by id desc) grp
    from mytable t
) t
order by id

Demo on DB Fiddlde:

id | string | is_sep | rn | rn_desc
-: | :----- | -----: | -: | ------:
 1 | XX     |      0 |  1 |       3
 2 | XX     |      0 |  2 |       2
 3 | XX     |      1 |  3 |       1
 4 | XX     |      0 |  1 |       3
 5 | XX     |      0 |  2 |       2
 6 | XX     |      1 |  3 |       1
 7 | YY     |      0 |  1 |       4
 8 | YY     |      0 |  2 |       3
 9 | YY     |      0 |  3 |       2
10 | YY     |      1 |  4 |       1
11 | ZZ     |      0 |  1 |       2
12 | ZZ     |      1 |  2 |       1
13 | ZZ     |      0 |  1 |       3
14 | ZZ     |      0 |  2 |       2
15 | ZZ     |      1 |  3 |       1