mysql - 缺失范围和连续范围
初始化数据
# 创建表
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 - 缺失范围和连续范围的更多相关文章
- MySQL缺失mysql_config文件
打算爬虫,安装mysqldb 结果使用pip安装出错 在centos-6.4上pip install mysql-python,报错如下[sentry@kjtest111 mysql-python]$ ...
- [翻译]——MySQL 8.0 Histograms
前言: 本文是对这篇博客MySQL 8.0 Histograms的翻译,翻译如有不当的地方,敬请谅解,请尊重原创和翻译劳动成果,转载的时候请注明出处.谢谢! 英文原文地址:https://lefred ...
- MYSQL删除表的记录后如何使ID从1开始
MYSQL删除表的记录后如何使ID从1开始 MYSQL删除表的记录后如何使ID从1开始 http://hi.baidu.com/289766516/blog/item/a3f85500556e2c09 ...
- MYSQL主键自动增加的配置及auto_increment注意事项
文章一 原文地址: http://ej38.com/showinfo/mysql-202971.html 文章二: 点击转入第二篇文章 在数据库应用,我们经常要用到唯一编号.在MySQL中可通过字 ...
- MySQL 8.0有什么新功能
https://mysqlserverteam.com/whats-new-in-mysql-8-0-generally-available/ 我们自豪地宣布MySQL 8.0的一般可用性. 现在下载 ...
- centos 离线安装 mysql 5.7
1 . 安装新版mysql前,需将系统自带的mariadb-lib卸载. rpm -qa|grep mariadb mariadb-libs--.el7.centos.x86_64 rpm -e -- ...
- mysql 清空或删除表数据后,控制表自增列值的方法
http://blog.sina.com.cn/s/blog_68431a3b0100y04v.html 方法1: truncate table 你的表名 //这样不但将数据全部删除,而且重新定位自增 ...
- mysql basic operation,mysql总结,对mysql经常使用语句的详细总结,MySQL学习笔记
mysql> select * from wifi_data where dev_id like "0023-AABBCCCCBBAA" ; 1.显示数据库列表.show d ...
- 面试中问你MySql,这一篇就够了
说一说主键索引与唯一索引 主键是一种约束,唯一索引是一种索引,两者在本质上是不同的. 主键索引默认是聚簇索引.唯一索引一般是非聚簇索引. 主键索引不能为空,唯一索引在InnoDB中可以出现多个null ...
随机推荐
- linux下解压大于4G文件提示error: Zip file too big错误的解决办法
error: Zip file too big (greater than 4294959102 bytes)错误解决办法.zip文件夹大于4GB,在centos下无法正常unzip,需要使用第三方工 ...
- 116、Android获取Manifest中<meta-data>元素的值
在AndroidManifest.xml中,<meta-data>元素可以作为子元素, 被包含在<activity>.<application> .<serv ...
- System.Drawing.Color
System.Drawing.Color color=Color.Red; System.Drawing.Color color=Color.FromArgb(,,); System.Drawing. ...
- OJ提交题目中的语言选项里G++与C++的区别(转)
G++? 首先更正一个概念,C++是一门计算机编程语言,G++不是语言,是一款编译器中编译C++程序的命令而已. 那么他们之间的区别是什么? 在提交题目中的语言选项里,G++和C++都代表编译的方式. ...
- PSP(11.16~11.23)
18号 类别c 内容c 开始时间s 结束e 中断I 净时间T 看书 构建之法 9:00 10:00 0 60m 看书 查资料 10:00 11:15 5 70m 个人 写博客 13:30 14:55 ...
- Latex感想
看人家,一个小女生,被导师逼着,首先对电脑方面理解不多,3天时间,latex已经把Paper框架建立起来,我可以说我自愧不如吗?德鲁克<卓有成效的管理者>说的一次干一件事情,<冬吴相 ...
- Linux下的shell编程(三)BY 四喜三顺
正则表达式:-------------------------------------------------------------------------------------------^ ...
- Chrome和Firefox浏览器执行new Date() 函数传参数得到不同结果的陷阱
某日,同事问到关于new Date() 函数传参数,在火狐浏览器和谷歌浏览器控制台运行,会得到不同的结果,刚开始觉得不可能,后来实际操作才发现此陷阱 var date = new Date('2014 ...
- Nopcommerce 二次开发1 基础
1 Doamin 酒店 namespace Nop.Core.Domain.Hotels { /// <summary> /// 酒店 /// </summary> p ...
- Tiny_4412的NFS挂载
设备连接: 交叉网线 串口线 usb线 电源线 网络设置: 笔记本ubuntu:wifi处,设置IPv4设置“仅本地连接”,不要 ...