VFP SQL-select查询连续号段范围及断号问题

作者在 2014-12-05 09:11:21 发布以下内容
VFP SQL-select查询连续号段范围及断号问题
 问题:有一列数字{7,88,9,8,103,12,11,102,101},有两个问题:
(1)找出连续段并记录连续段的起、始值;
(2)找出数列中间的中断部分。
对于前一个问题,网上流行的有好多例子,针对mysql、sql等等的都有,就是没找到针对VFP,仔细学习了一下,发现原理只有一个: 依有序数列与项号的关系进行分组查询
实现的方法步骤:
(1)按由小到大的顺序进行排序;
(2)与对应项号做差;
(3)根据差值进行分组;
(4)取得每组的最小值与最大值。
而对于后一个问题网上的介绍很少,在此文中准备使用VFP SQL-select来分析解决这两个问题。
首先,建立数据表并准备测试数据
CREATE TABLE test (数字 N(5,0))
INSERT INTO test values(7)
INSERT INTO test values(88)
INSERT INTO test values(9)
INSERT INTO test values(8)
INSERT INTO test values(103)
INSERT INTO test values(12)
INSERT INTO test values(11)
INSERT INTO test values(102)
INSERT INTO test values(101)
数据准备好了,先来解决第一个问题。
第一步:排序
 SELECT 数字 FROM test ORDER BY 数字
图片
第二步: 生成项号(即行号或者记录号)
SELECT a.数字,RECNO() as 项号 FROM (;
SELECT 数字 FROM test ORDER BY 数字) a 
图片
第三步:数字与项号做差 
SELECT b.数字,b.项号,b.数字-b.项号 as 分组 FROM (;
SELECT a.数字,RECNO() as 项号 FROM (;
SELECT 数字 FROM test ORDER BY 数字) a) b 
图片
第四步:生成结果 
SELECT c.分组,MIN(c.数字) as 起,MAX(c.数字) as 止 FROM (;
SELECT b.数字,b.项号,b.数字-b.项号 as 分组 FROM (;
SELECT a.数字,RECNO() as 项号 FROM (;
SELECT 数字 FROM test ORDER BY 数字) a) b) c GROUP BY c.分组 
图片
至此,第一个问题算是解决了,那么我们来分析第二个问题。 观察第一个问题的最后结果,不难发现第二个问题的答案
10,10
13,87 
89,100
 也能发现其实就是:每一行“止”+1为起始,下一行“起”-1为终了,为此,执行了下边的命令
SELECT c.分组,Max(c.数字)+1 as 起,Min(c.数字)-1 as 止 FROM (;
SELECT b.数字,b.项号,b.数字-b.项号 as 分组 FROM (;
SELECT a.数字,RECNO() as 项号 FROM (;
SELECT 数字 FROM test ORDER BY 数字) a) b) c GROUP BY c.分组
得出
图片
看着这个结果,觉得把“止”列往前移上一行和“起”列错位对应起来,再把有空值的行去掉就应该是结果了,试试下边命令:
SELECT DISTINCT e.起,f.止 FROM (;
SELECT c.分组,Max(c.数字)+1 as 起,Min(c.数字)-1 as 止 FROM (;
SELECT b.数字,b.项号,b.数字-b.项号 as 分组 FROM (;
SELECT a.数字,RECNO() as 项号 FROM (;
SELECT 数字 FROM test ORDER BY 数字) a) b) c GROUP BY c.分组) d,(;
SELECT 起,RECNO() as 行号 FROM d) e,(;
SELECT 止,RECNO() as 行号 FROM d) f WHERE e.行号+1=f.行号
得出
图片
到此也就解决了第二个问题。
由于个人水平所限,命令可能写的不明了简单,但总算是能达到目的,顺便感慨一下select命令的强大 。


 
最后也附上网友们在Sql及Mysql里的解决第一个问题的办法。
<转载一:sql实现>
学习-SQL查询连续号码段的巧妙解法

作者:eygle | English 【转载时请标明出处和作者信息】【恩墨学院 OCM培训传DBA成功之道】

在ITPUB上有一则非常巧妙的SQL技巧,学习一下,记录在这里。

最初的问题是这样的:

我有一个表结构,
fphm,kshm
2014,00000001
2014,00000002
2014,00000003
2014,00000004
2014,00000005
2014,00000007
2014,00000008
2014,00000009
2013,00000120
2013,00000121
2013,00000122
2013,00000124
2013,00000125


(第二个字段内可能是连续的数据,可能存在断点。)

怎样能查询出来这样的结果,查询出连续的记录来。
就像下面的这样?
2014,00000001,00000005
2014,00000009,00000007
2013,00000120,00000122
2013,00000124,00000125


ITPUB上的朋友给出了一个非常巧妙的答案:


SQL> SELECT b.fphm, MIN (b.kshm) Start_HM, MAX (b.kshm) End_HM
2 FROM (SELECT a.*, TO_NUMBER (a.kshm - ROWNUM) cc
3 FROM (SELECT *
4 FROM t
5 ORDER BY fphm, kshm) a) b
6 GROUP BY b.fphm, b.cc
7 /

FPHM START_HM END_HM
---------- -------- --------
2013 00000120 00000122
2013 00000124 00000125
2014 00000001 00000005
2014 00000007 00000009


巧思妙想,就在一念之间。
ITPUB其他参考链接如下:
http://blog.itpub.net/post/5042/27936

-The End-

<转载二:mysql实现>
关于数字的经典SQL编程:连续范围问题

2012年12月29日10:56 it168网站原创 作者:姜承尧 编辑:王玉圆

 【IT168 技术】连续范围问题也是一个非常经典的SQL编程问题。为了使讲解易于理解,我们先来创建一些测试数据。

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->CREATE TABLE t ( a INT UNSIGNED NOT NULL PRIMARY KEY );

INSERT INTO t VALUES(
1);
INSERT INTO t VALUES(
2);
INSERT INTO t VALUES(
3);
INSERT INTO t VALUES(
100);
INSERT INTO t VALUES(
101);
INSERT INTO t VALUES(
103);
INSERT INTO t VALUES(
104);
INSERT INTO t VALUES(
105);

  可以看到1~3是连续的,100~101是连续的,103~105是连续的,那么怎么能得到如下表所示的结果呢?

关于数字的经典SQL编程:连续范围问题
▲连续范围

  我们来看下面这句SQL语句及其返回的结果集。


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->mysql> SELECT a,@a:=@a+1 rn FROM t,(SELECT @a:=0) AS a;
+-----+------+
| a   | rn   |
+-----+------+
|  
1 |    1 |
|  
2 |    2 |
|  
3 |    3 |
|
100 |    4 |
|
101 |    5 |
|
103 |    6 |
|
104 |    7 |
|
105 |    8 |
+-----+------+
8 rows in set (0.00 sec)

  rn列是人为计算出来的行号。是不是可以通过连续给出的行号来反映出连续范围的规律呢?如果还没有看出,那么再看下面这个SQL及它的返回结果集。


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->mysql> SELECT a,rn,a-rn
    
-> FROM
    
-> (SELECT a,@a:=@a+1 rn FROM t,(SELECT @a:=0) AS a)
    
-> AS b;
+-----+------+------+
| a   | rn   | a
-rn |
+-----+------+------+
|  
1 |    1 |    0 |
|  
2 |    2 |    0 |
|  
3 |    3 |    0 |
|
100 |    4 |   96 |
|
101 |    5 |   96 |
|
103 |    6 |   97 |
|
104 |    7 |   97 |
|
105 |    8 |   97 |
+-----+------+------+
8 rows in set (0.00 sec)

  是的,在同一组连续值内,连续数值的差是一个常量,因为组内没有间断。当出现一个新组时,其列和行号之间的差值开始增大。所以对于连续范围的统计,我们可以根据差值来进行分组统计,具体过程如下:


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->mysql> SELECT MIN(a) start_range,MAX(a) end_range
    
-> FROM
    
-> (
    
-> SELECT a,rn,a-rn AS diff
    
-> FROM
    
-> (SELECT a,@a:=@a+1 rn FROM t,(SELECT @a:=0) AS a)
    
-> AS b
    
->) AS c
    
-> GROUP BY diff
    
-> ;
+-------------+-----------+
| start_range | end_range |
+-------------+-----------+
|          
1 |         3 |
|        
100 |       101 |
|        
103 |       105 |
+-------------+-----------+
3 rows in set (0.00 sec)
vfp | 阅读 6403 次
文章评论,共0条
游客请输入验证码
浏览113397次
最新评论