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 ...
随机推荐
- 红黑树(Red-Black tree)
红黑树又称红-黑二叉树,它首先是一颗二叉树,它具体二叉树所有的特性.同时红黑树更是一颗自平衡的排序二叉树.我们知道一颗基本的二叉树他们都需要满足一个基本性质–即树中的任何节点的值大于它的左子节点,且小 ...
- [AIR] 获取U盘,打开U盘
示例: 获取存储卷的方法: package com.controls { import flash.events.StorageVolumeChangeEvent; import flash.file ...
- hmtl弹出框样式
@model Web.Manager.Models.SendMessage @{ ViewBag.Title = "消息发布"; Layout = null;} <link ...
- ipad2 恢复
1.用原装充电线连接电脑,并打开itunes~2.同时按住电源键和home键 10秒左右,直到白苹果画面变成黑屏3.按住home键~但要松开电源键,继续等待~直到ipad出现画面(如图) 4.这时候, ...
- fgtyn
http://www.studiocleo.com/projects/ballettechnique/one_11.html
- canvas生成二维码,并下载保存为本地的图片
function getTicket(id,salt){//qrcode生成canvas二维码 $(".zc-mask").show(); $(".edit-box&qu ...
- sql 删除重复数据且保留其中一条 用sql 关键字:with ROW_NUMBER
--1.建立表:Coursecreate table Course( ID int identity(1,1),--ID Student varchar(20) ,--学生 Sub varchar(2 ...
- Junit4断言
Junit4断言API: http://junit.org/javadoc/latest/index.html Constructor Summary protected Assert() ...
- 《JavaScript高级程序设计》学习笔记(4)——引用类型
欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 本节内容对应<JavaScript高级程序设计>的第五章内容. 在ECMAScript中, ...
- CHARINDEX
实现查询条件多个值的或的关系 Select Id,Name from CustTable where CharIndex( CustTable.Name, 'ACDE,BEX,CCC')>0 C ...