找到顺序运行的开始和结束值

gue*_*est 5 mysql gaps-and-islands mysql-5.6

这篇文章与我需要的相反: 查找 [1, 161] 中的哪些数字不在结果集中?

鉴于他们使用的样本数据:

mysql> CREATE TABLE wp_blogs
    -> (
    ->   blog_id INTEGER
    -> );

mysql> insert into wp_blogs values(1);
mysql> insert into wp_blogs values(2);
mysql> insert into wp_blogs values(4);
mysql> insert into wp_blogs values(6);
mysql> insert into wp_blogs values(7);
mysql> insert into wp_blogs values(8);
mysql> insert into wp_blogs values(10);
Run Code Online (Sandbox Code Playgroud)

此查询回答了“差距是什么?”的问题:

mysql> SELECT a.blog_id+1 AS start, MIN(b.blog_id) - 1 AS end
    ->     FROM wp_blogs AS a, wp_blogs AS b
    ->     WHERE a.blog_id < b.blog_id
    ->     GROUP BY a.blog_id
    ->     HAVING start < MIN(b.blog_id);

+-------+------+
| start | end  |
+-------+------+
|     3 |    3 |
|     5 |    5 |
|     9 |    9 |
+-------+------+
Run Code Online (Sandbox Code Playgroud)

我想知道这些岛屿是什么?我希望看到这样的输出:

+-------+------+  
| start | end  |  
+-------+------+  
|     1 |    2 |  
|     4 |    4 |  
|     6 |    8 |  
|    10 |   10 |  
+-------+------+  
Run Code Online (Sandbox Code Playgroud)

但我无法弄清楚这样做的查询。我正在使用 MySQL 5.6。

有人有解决方案吗?

Ric*_*mes 0

@variables 是秘密武器。(或 MariaDB 10.0.2 的“窗口函数”。)

您知道如何获得“间隙”3、5、9。每个少一个就是一个岛的“结束”,多一个就是下一个岛的开始。

因此,遍历间隙表,使用 @variable 来跟踪“前一个”末端,等等。

SELECT @prev+1 AS 'start',
       `start`-1 AS 'end',
       @prev := `end` AS junk
    FROM ( SELECT @prev := 0 ) AS init
    JOIN gaps
Run Code Online (Sandbox Code Playgroud)

该查询中有两个缺陷(留给读者作为练习):

  • 无法生成最后一行。(使用UNIONORDER BY
  • 生成一个额外的列。(将此查询包装在另一个查询中。)
  • 我没有验证您的“差距”查询;如果失败,则将两个查询组合在一起。