初始化数据

# 创建表
DROP TABLE IF EXISTS g;
CREATE TABLE g(
a INT
)ENGINE=INNODB; # 初始化数据
INSERT INTO g SELECT 1;
INSERT INTO g SELECT 2;
INSERT INTO g SELECT 3;
INSERT INTO g SELECT 100;
INSERT INTO g SELECT 101;
INSERT INTO g SELECT 103;
INSERT INTO g SELECT 104;
INSERT INTO g SELECT 105;
INSERT INTO g SELECT 106;

对于g表其缺失范围如4-16所示

对于g表其连续范围如4-17所示

对于缺失范围的问题,可以通过下列步骤来解决

1)找到间断点之前的值,然后对该值加1,即为start_range;

2)找到间断点之前的值,然后对该值减1,即为end_range;

对于间断点之前的值,可以用如下sql:

SELECT a
FROM g AS A
WHERE NOT EXISTS(
SELECT *
FROM g AS B WHERE A.a+1=B.a
)

查出的106是无用的,因为它是表中的最大值,所以将其过滤掉。断点之前的值,对该值加1操作,即为start_range,可以通过以下sql语句得到:

SELECT a+1 start_range
FROM g AS A
WHERE NOT EXISTS(
SELECT *
FROM g AS B WHERE A.a+1=B.a
) AND a < (SELECT MAX(a) FROM g)

最后通过子查询为每个最小间断点返回表g中下一个已有的值并减一,即得到间断点end_range,最终sql语句如下所示:

SELECT a+1 start_range, (
SELECT MIN(a)-1
FROM g C WHERE C.a > A.a
) AS end_range
FROM g AS A
WHERE NOT EXISTS(
SELECT *
FROM g AS B WHERE A.a+1=B.a
) AND a < (SELECT MAX(a) FROM g)

这只是该问题的解决方案之一,更为简单直观的方法是,将表g中的数据进行移位匹配,如果是连续的值,那么其差值应该为1,如果不是连续的值就应该大于1

对于表g,进行移位匹配后应该得到如表4-18所示的内容。

可以看出next - cur的值等于1表示连续的值,否则不连续,不连续的值为(3,100)、(101,103),而我们要求的不连续范围为(4,99)、(102,102),也就是(cur+1,next-1)就是我们要的确实范围,要得到图4-18所示的内容,可以执行下述SQL:

SELECT A.a AS cur,(
SELECT MIN(a)
FROM g AS B WHERE B.a > A.a
) AS next
FROM g AS A

而要得到最终的结果,只需要对cur加1,next减1即可。该好处另外一个好处是无需处理最大值,因为最大数next的值为NULL。该解决方案的SQL语句如下所示:

SELECT cur+1 AS start_range, NEXT-1 AS end_range
FROM (
SELECT A.a AS cur,(
SELECT MIN(a)
FROM g AS B WHERE B.a > A.a
) AS NEXT
FROM g AS A
) AS C
WHERE NEXT-cur > 1;

连续范围,如果采用子查询方案,我们要手动创建一个列,并对这个列进行分组。这个列应该是每个连续分组的最大值,对于{1,2,3}来说,这个最大值就应该是3。计算一组连续组中最大值所依据的原理是:返回大于或等于当前值且后面一个值为间断点的最小值。下面是该子查询的SQL:

SELECT a,(
SELECT MIN(a)
FROM g AS A
WHERE NOT EXISTS(
SELECT *
FROM g AS B
WHERE A.a+1 = B.a
) AND A.a >= C.a
) AS MAX
FROM g AS C

剩下的工作就就简单了,在上一步查询中执行如下语句对max列进行分组,得到分组中的最小值和最大值,这就是我们要的连续范围。

SELECT MIN(a) AS start_range, MAX(a) AS end_range
FROM(
SELECT a,(
SELECT MIN(a)
FROM g AS A
WHERE NOT EXISTS(
SELECT *
FROM g AS B
WHERE A.a+1 = B.a
) AND A.a >= C.a
) AS MAX
FROM g AS C
) AS D
GROUP BY MAX;

上述查询给出了连续范围问题的解决方案,但其性能是值得商榷的。这里的扫描成本是O(N²)。对于表中数据量非常大的情况,其性能又会变得十分糟糕。因此解决连续范围问题的最优方案是采用行号方法。

SELECT MIN(a) AS start_range, MAX(a) AS end_range
FROM
(
SELECT a, rn, a-rn AS diff
FROM
(
SELECT a, @a:=@a+1 rn FROM g,
(SELECT @a:=0) AS aa
) AS b
) AS c
GROUP BY diff;

mysql - 缺失范围和连续范围的更多相关文章

  1. MySQL缺失mysql_config文件

    打算爬虫,安装mysqldb 结果使用pip安装出错 在centos-6.4上pip install mysql-python,报错如下[sentry@kjtest111 mysql-python]$ ...

  2. [翻译]——MySQL 8.0 Histograms

    前言: 本文是对这篇博客MySQL 8.0 Histograms的翻译,翻译如有不当的地方,敬请谅解,请尊重原创和翻译劳动成果,转载的时候请注明出处.谢谢! 英文原文地址:https://lefred ...

  3. MYSQL删除表的记录后如何使ID从1开始

    MYSQL删除表的记录后如何使ID从1开始 MYSQL删除表的记录后如何使ID从1开始 http://hi.baidu.com/289766516/blog/item/a3f85500556e2c09 ...

  4. MYSQL主键自动增加的配置及auto_increment注意事项

    文章一 原文地址: http://ej38.com/showinfo/mysql-202971.html 文章二:   点击转入第二篇文章 在数据库应用,我们经常要用到唯一编号.在MySQL中可通过字 ...

  5. MySQL 8.0有什么新功能

    https://mysqlserverteam.com/whats-new-in-mysql-8-0-generally-available/ 我们自豪地宣布MySQL 8.0的一般可用性. 现在下载 ...

  6. centos 离线安装 mysql 5.7

    1 . 安装新版mysql前,需将系统自带的mariadb-lib卸载. rpm -qa|grep mariadb mariadb-libs--.el7.centos.x86_64 rpm -e -- ...

  7. mysql 清空或删除表数据后,控制表自增列值的方法

    http://blog.sina.com.cn/s/blog_68431a3b0100y04v.html 方法1: truncate table 你的表名 //这样不但将数据全部删除,而且重新定位自增 ...

  8. mysql basic operation,mysql总结,对mysql经常使用语句的详细总结,MySQL学习笔记

    mysql> select * from wifi_data where dev_id like "0023-AABBCCCCBBAA" ; 1.显示数据库列表.show d ...

  9. 面试中问你MySql,这一篇就够了

    说一说主键索引与唯一索引 主键是一种约束,唯一索引是一种索引,两者在本质上是不同的. 主键索引默认是聚簇索引.唯一索引一般是非聚簇索引. 主键索引不能为空,唯一索引在InnoDB中可以出现多个null ...

随机推荐

  1. Laravel 使用多个数据库的问题。

    这几天在使用Laravel 开发一个系统.这个系统连2个数据库.一个名为blog,一个名为center. center 数据库的作用是作为用户中心.可能会有其他几个系统相连,属于公用数据库.主要是用来 ...

  2. NLP情感分析监督学习样本打标

    1). 情感打标 a). 全句 单句 标签 好吃是好吃 pos 真材实料 pos 不过感觉一人份的量就有点小贵 neg 点的是肥牛米线 neu b). 全文本 文本 标签 分量足,味道不错,味道也不错 ...

  3. web.py学习心得

    1.注意判断数字时,如果是get传递的参数,一定要用int转换.不然出错. 2.$var 定义时,冒号后的内容不是python内容,需加上$符号.如$var naviId:$naviId. 3.各个模 ...

  4. "\r\n","\r","\n"

    参考: http://blog.csdn.net/xiaofei2010/article/details/8458605 '\r' : 回车符 '\n' : 换行符 以下是c++语言的测试代码, 跟平 ...

  5. 从零开始系列--R语言基础学习笔记之一 环境搭建

    R是免费开源的软件,具有强大的数据处理和绘图等功能.下面是R开发环境的搭建过程. 一.点击网址 https://www.r-project.org/ ,进入"The R Project fo ...

  6. ASP.NET网站中获取当前虚拟目录的应用程序目录的方法(转)

    [原创]ASP.NET网站中获取当前虚拟目录的应用程序目录的方法 ASP.NET网站中获取当前虚拟目录的应用程序目录的方法1.问题描述:有时候,某个网页控件会被不同目录下文件使用,此时如果该控件中有一 ...

  7. backtrack下vim的使用

    root@bt:~# vim test.c //vim新建或者编辑test.c,执行后进入vim编辑器,按a键进入编辑状态,输入C代码 #include<stdio.h> void mai ...

  8. iPad 控件UIPopoverController使用

    UIPopoverController 是iPad特有控件,(iOS7-9),在iOS9之后别废弃 使用步骤 设置内容控制器 UIPopoverController直接继承NSObject,不具备可视 ...

  9. (Hibernate进阶)Hibernate映射——一对一单向关联映射(五)

    映射原理 两个实体对象之间是一对一的关联映射,即一个对象只能与另外唯一的一个对象相对应.例如:一个人(Person)只有一张身份证(IdCard).我们看一下这个例子的对象模型,如下图所示: 对象模型 ...

  10. Spring 事务处理

    Spring 默认执行事务回滚:当开启事务的类中对数据库的操作的异常没有任何处理时,才会主动触发事务回滚. 而很多时候业务都需要对抛出的异常进行处理,所以如果try,catch了操作数据库的方法,事务 ...