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

Posted

技术标签:

【中文标题】根据sql server 2012中后续行索引之间的差异创建分区【英文标题】:create partition based on the difference between subsequent row indices in sql server 2012 【发布时间】:2016-09-15 05:27:25 【问题描述】:

我使用的是 SQL Server 2012。

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

  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' )

【问题讨论】:

SQL Server 的哪个版本? @shree.pat18 已更新 【参考方案1】:

试试这个:

    ;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 并分配之后的所有记录 指向一个“组”,直到找到下一个差异 1。这是 分组的关键步骤。 最后一步是使用dense_rank over 上一步计算得到行号的指标 根据需要。

此解决方案确实有一个限制,如果差异不是按递增顺序排列的,即如果您在样本数据中还有两个值(例如 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 步中,我们只检查连续值之间差异的不同值的转换,而不是使用最小/最大函数。然后排名使用条件和为原始数据中的每个值分配一个组。

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

【讨论】:

如果我想在 2008 年实现这一点,唯一的方法是创建多个 CTE 在 b.row_index = a.row_index - 1 等上加入它们【参考方案2】:

如果有大量记录,它可能会表现不佳,但请尝试一下:

;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

【讨论】:

以上是关于根据sql server 2012中后续行索引之间的差异创建分区的主要内容,如果未能解决你的问题,请参考以下文章

列存储索引中列的顺序在 SQL Server 2012 中是不是重要

sql server 索引总结三

sql server 2012中插入记录INSERT后面+INTO与不+之间有啥区别?

译索引进阶:SQL SERVER中的索引碎片下篇

转换 SQL Server 2008 R2 和 2012 之间的差异

SQL Server和Oracle数据库索引介绍