将数字间隔分成组

Posted

技术标签:

【中文标题】将数字间隔分成组【英文标题】:Split intervals of numbers into groups 【发布时间】:2016-08-25 11:30:57 【问题描述】:

我有下面的数字序列,每次后面的数字与前一个值的差异超过一个单位时,我想创建一组新的数字,即打破连续间隔

表T

value
1 
2
3
5
6
7
15
16
17
18

要组成连续区间的组:

min max
1   3
5   7
15  18

我正在尝试使用 dense_rank() 函数对行进行编号,如下例所示,然后我将能够按 rankNumber 分组并获得 MIN(value) 和 MAX(value),但我没有找到模式在此函数的 PARTITION BY 子句中使用

value rankNumber
1     1
2     1
3     1
5     2
6     2
7     2
15    3
16    3
17    3
18    3

    WITH T2 AS
    (
     SELECT value, LEAD(value) OVER(ORDER BY value) as nextValue
     FROM T 
    )

    SELECT value, DENSE_RANK() 
     OVER(PARTITION BY CASE WHEN nextValue - value > 1 THEN 1 ELSE 0 END ORDER BY value)
    FROM T2

创建表的代码:

CREATE TABLE t(
    value   INT
);
INSERT INTO t VALUES
    (1), (2), (3), (5), (6), (7), (15), (16), (17), (18);

使用上述查询的当前输出:

value rankNumber
1     1
2     2
3     1
5     3
6     4
7     2
15    5
16    6
17    7
18    8

【问题讨论】:

您可能对this answer to, "Solving “Gaps and Islands” with row_number() and dense_rank()?感兴趣 【参考方案1】:

您需要想出一些方法将序列转换为相应的组。我刚刚从这里的另一个用户那里学到了这个技巧。通过使用贯穿所有记录的ROW_NUMBER,您可以通过从该行号中减去同一记录上的value 来计算组键。如果values 是连续的,则减法结果不会发生变化(因此产生了相同的组密钥)。否则组键将跳转到下一个(较小的)值。每次跳跃,组键都会变小。

这里是查询:

select min(value) min, max(value) max
from (select value, ROW_NUMBER() over (order by value) - value as [key] 
      from t) v
group by [key]
order by min

【讨论】:

这是一个很好的答案! :) @EvaldasBuinauskas 是的,这个想法很有趣:) 正如我的回答中提到的,这个想法最初来自这里***.com/a/36927721/1679602(如果你有兴趣 - 我昨天刚刚读过那个答案) . 关于这个方法的解释,你可能有兴趣this answer to, "Solving “Gaps and Islands” with row_number() and dense_rank()?

以上是关于将数字间隔分成组的主要内容,如果未能解决你的问题,请参考以下文章

递归练习1,数字分组

如何将一个集合分成两个子集,以使两个集合中数字之和之间的差异最小?

用C语言写:36个数字平均分成4组(每组九个数字)有多少种分法,并显示分组

将数字分组 C++

如何在100万个整数中 选出最大的10个 java

求java程序:输入n个正整数,分成两组求和,求两列数字组合使这两组的和最接近平均数