根据 sql 服务器 2012 中后续行索引之间的差异创建分区

create partition based on the difference between subsequent row indices in sql server 2012

我正在使用 SQL Server 2012。

我想根据后续行中的索引是否增加 1 或更多来创建一个 row_number。例如,假设我有一个 table 看起来像:

  event row_index
    1       24          
    2       25  
    3       26
    4       30
    5       31
    6       42 
    7       43
    8       44
    9       45

然后我想做的是在最后创建一个列,称为 seq_ID:

event    row_index   seq_id
    1       24         1         
    2       25         1
    3       26         1
    4       30         2
    5       31         2
    6       42         3
    7       43         3
    8       44         3
    9       45         3

基本上,seq_id 只有在后续行索引之间的差异大于 1 时才有机会。我尝试使用:

rank() over (partition by 'not sure what to put here' )

试试这个:

    ;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 使用 lag 函数获取差异 (从 SQL Server 2012 开始可用)。
  • 接下来计算CTE 当差异超过 1 并分配之后的所有记录 指向一个'group',直到找到下一个差异<> 1。这是 分组的关键步骤。
  • 最后一步是使用dense_rank 上一步计算得到行号的指标 根据需要。

此解决方案确实有一个 限制,因为如果差异不是按递增顺序排列,即如果示例数据中有两个以上的值(例如 52 和 53),它将失败, 它会将它们分类到第 3 组而不是创建一个新组。

Demo

更新:以下方法可以克服上述限制:

    ;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

第一步还是一样。但是在第 2 步中,我们只检查过渡到不同值的连续值之间的差异,而不是使用 min/max 函数。然后排名使用条件总和为原始数据中的每个值分配一个组。

Demo

这可以进一步简化为:

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

对于大量记录,它可能表现不佳,但请尝试一下:

;with T as (
 select event, rowindex, rowindex-row_number() over (order by event) as rn from YourTableName
)
select event, (select count(distinct rn)+1 from T where rn<TT.rn) as seq_id
 from T TT order by event