【问题标题】:SQL query to extract ranges from table of integersSQL查询从整数表中提取范围
【发布时间】:2014-12-03 15:16:43
【问题描述】:

这可能以前已经在这里回答过,但我不知道如何搜索它,所以如果它是重复的,我很抱歉。我有一个带有整数列的表,它按顺序保存数字。

由于删除行而丢失了一些数字:

+-------+
| _auto |
+-------+
|   0   |
|   1   |
|   2   |
|  5    |
|  6    |
|  7    |
|   9   |
|  11   |
|  12   |
|  13   |
|  14   |
|   16  |
|   17  |
|  19   |
|  20   |
+-------+

我想要的是编写 SQL 查询,它给了我一个由该列上的范围组成的表。

+----+----+
|  F |  T |
+----+----+
|  0 |  2 |
|  5 |  7 |
|  9 |  9 |
| 11 | 14 |
| 16 | 17 |
| 19 | 20 |
+----+----+

我会将它与 QT4::QSqlDatabase 驱动程序一起使用,所以如果它可以在任何兼容的数据库 (ANSI SQL) 上工作,而不仅仅是 PostgreSQL,那就太好了。

我相信这个算法:(1)选择行,这样就没有值的行_auto+1; (2) 相同,但 _auto-1; (3) 联合这两个选择。

但我不明白如何写前两个选择。

【问题讨论】:

    标签: sql select sequence gaps-and-islands ansi-sql


    【解决方案1】:

    数字序列有一个属性:如果你从它们中减去一个序列,那么结果就是一个常数。以下查询使用此观察结果:

    select min(_auto) as f, max(_auto) as t
    from (select n._auto, row_number() over (order by n._auto) as seqnum
          from numbers n
         ) n
    group by (_auto - seqnum);
    

    【讨论】:

    • 好吧,我花了一段时间试图理解它是如何工作的,这是一个外行的解释:假设你有一个数字序列1, 2, 3, 150, 151, 152row_number() 将输出按数字排序的每一行的索引 (order by n._auto)。这给出了1, 2, 3, 4, 5, 6 (seqnum)。然后 group by 子句在原始数字上的末尾组减去 seqnum,在本例中为 0, 0, 0, 146, 146, 146。然后它输出这些行的最小值和最大值。想想就觉得很有意义,但需要一段时间才能理解。
    猜你喜欢
    • 1970-01-01
    • 2012-04-22
    • 2023-02-25
    • 1970-01-01
    • 1970-01-01
    • 2020-05-14
    • 1970-01-01
    • 2014-10-28
    • 2019-10-15
    相关资源
    最近更新 更多