| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4271 人关注过本帖
标题:指定区间求和
只看楼主 加入收藏
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:335
帖 子:9848
专家分:27241
注 册:2012-2-5
收藏
得分:0 
程序代码:
* 生成测试表
CREATE CURSOR 测试 (序号 I,值 I)
NVAL=10000002
FOR I=1 TO NVAL
    INSERT INTO 测试 VALUES (I,I)
ENDFOR

* 生成区间表
CREATE CURSOR 区间 (X I,Y I,Z I)
J=0
FOR I=1 TO INT(NVAL/6) STEP 6
    J=J+1
    INSERT INTO 区间 VALUES (I,I+5,J)
ENDFOR

* 测试方法1_SQL查询
*!*    T1=SECONDS()
*!*    Select Transform(X) + "-" + Transform(Y) + SPACE(10) As  区间, Sum(值) As 求和 Where 序号 Between X And Y group by z From 测试, 区间  into cursor ttt
*!*    MESSAGEBOX("共用时 "+TRANSFORM(SECONDS()-T1)+" 秒")
*!*    Browse

* 测试方法2_VFP

* 求和结果表
T1=SECONDS()
CREATE CURSOR 结果 (区间 C(20),和 N(8))
NSUM=0
SELECT 测试
SCAN
    NSUM=NSUM+IF MOD(序号,6)=0
        INSERT INTO 结果 VALUES (TRANSFORM(测试.序号-5)+"-"+TRANSFORM(测试.序号),NSUM)
        NSUM=0
    ENDIF
ENDSCAN
MESSAGEBOX("共用时 "+TRANSFORM(SECONDS()-T1)+" 秒")
SELECT 结果
BROWSE

如果记录数达到10万条以上,SQL命令处理数据所用时间与VFP命令处理数据所用时间,就不是一个档次了。

坚守VFP最后的阵地
2016-05-02 18:46
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:335
帖 子:9848
专家分:27241
注 册:2012-2-5
收藏
得分:0 
所以说,SQL查询命令,只是代码简练而已,但速度比起VFP可不是一个档次了。希望喜欢SQL查询命令的同行,慎用SQL命令。

坚守VFP最后的阵地
2016-05-02 18:51
aaaaaa
Rank: 8Rank: 8
等 级:贵宾
威 望:21
帖 子:796
专家分:937
注 册:2012-9-4
收藏
得分:0 
Close Databases

* 生成测试表
Create Cursor 测试 (序号 I,值 I)
NVAL=10000002
For I=1 To NVAL
    Insert Into 测试 Values (I,I)
Endfor

* 生成区间表
Create Cursor 区间 (X I,Y I,Z I)
J=0
For I=1 To Int(NVAL/6) Step 6
    J=J+1
    Insert Into 区间 Values (I,I+5,J)
Endfor



*!*    ================================================
*!*    不好意思,只快了 30% (快10+)秒。俺刘格艾还要努力
*!*    一条 SQL 查询语句,10,000,002(一千万条记录),SQL 的约20秒,VFP 的约 30秒

* 测试方法1_SQL
T1=Seconds()

Select Transform(序号 - 5) + "-" + Transform(序号) + Space(20) As 区间, ;
    (2*值 - 5)*3 As 和 From 测试 Where Mod(序号, 6) = 0 Into Cursor ttt

Messagebox("共用时 "+Transform(Seconds()-T1)+" 秒")
*!*    ================================================

Return


* 测试方法2_VFP

* 求和结果表
T1=Seconds()
Create Cursor 结果 (区间 C(20),和 N(8))
NSUM=0
Select 测试
Scan
    NSUM=NSUM+值
    If Mod(序号,6)=0
        Insert Into 结果 Values (Transform(测试.序号-5)+"-"+Transform(测试.序号),NSUM)
        NSUM=0
    Endif
Endscan
Messagebox("共用时 "+Transform(Seconds()-T1)+" 秒")
Select 结果
Browse

Return

民工子弟学校22班团小组长阳光模特队长冲锋篮球队前锋小苹果合唱队领唱蓝天舞蹈队编舞
2016-05-02 22:21
aaaaaa
Rank: 8Rank: 8
等 级:贵宾
威 望:21
帖 子:796
专家分:937
注 册:2012-9-4
收藏
得分:0 
所以说,SQL查询命令,不只是代码简练且优美,而且速度比起 XXX (此次屏蔽三个字,怕引起争论) 应该是一个档次了。希望喜欢SQL查询命令的同行,继续挖掘SQL命令。

这次先让让我们学生组 1:0,怎样?

民工子弟学校22班团小组长阳光模特队长冲锋篮球队前锋小苹果合唱队领唱蓝天舞蹈队编舞
2016-05-02 22:28
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10609
专家分:43210
注 册:2014-5-20
收藏
得分:0 
以下是引用aaaaaa在2016-5-2 22:28:04的发言:

所以说,SQL查询命令,不只是代码简练且优美,而且速度比起 XXX (此次屏蔽三个字,怕引起争论) 应该是一个档次了。希望喜欢SQL查询命令的同行,继续挖掘SQL命令。

这次先让让我们学生组 1:0,怎样?

从算法看,都是遍历一次就可搞定,两种方法差不多。
运行效率显然是SQL命令高,遍历循环体一个是编译指令,可直接放到指令寄存器执行;另一个是解释指令,要先解释成机器代码才可放到指令寄存器执行,显然循环次数越多,相对效率就越低。
有兴趣的可以这样测试:用编译语言(如ASM、C)写个扩展函数处理这个问题,提供给VFP调用,与用VFP代码的结果比较看看。

[此贴子已经被作者于2016-5-3 08:20编辑过]

2016-05-03 08:17
mywisdom88
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:191
帖 子:3147
专家分:8408
注 册:2015-3-25
收藏
得分:0 
以下是引用吹水佬在2016-5-3 08:17:57的发言:


从算法看,都是遍历一次就可搞定,两种方法差不多。
运行效率显然是SQL命令高,遍历循环体一个是编译指令,可直接放到指令寄存器执行;另一个是解释指令,要先解释成机器代码才可放到指令寄存器执行,显然循环次数越多,相对效率就越低。
有兴趣的可以这样测试:用编译语言(如ASM、C)写个扩展函数处理这个问题,提供给VFP调用,与用VFP代码的结果比较看看。

好像,循环次数多,真的效率差;其实,VFP或者SQL都可以优化的。
2016-05-03 09:10
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10609
专家分:43210
注 册:2014-5-20
收藏
得分:0 
优化一下还可以提高不少
图片附件: 游客没有浏览图片的权限,请 登录注册

程序代码:
Close Databases

* 生成测试表
Create Cursor 测试 (序号 I,值 I)
NVAL=10000002
For I=1 To NVAL
    Insert Into 测试 Values (I,I)
Endfor

* 生成区间表
Create Cursor 区间 (X I,Y I,Z I)
J=0
For I=1 To Int(NVAL/6) Step 6
    J=J+1
    Insert Into 区间 Values (I,I+5,J)
Endfor



*!*    ================================================
*!*    不好意思,只快了 30% (快10+)秒。俺刘格艾还要努力
*!*    一条 SQL 查询语句,10,000,002(一千万条记录),SQL 的约20秒,VFP 的约 30秒

* 测试方法1_SQL
T1=Seconds()

Select Transform(序号 - 5) + "-" + Transform(序号) + Space(20) As 区间, ;
    (2*- 5)*3 AsFrom 测试 Where Mod(序号, 6) = 0 Into Cursor ttt

?"方法1 共用时 "+Transform(Seconds()-T1)+" 秒"
*!*    ================================================

* 测试方法2_VFP

* 求和结果表
T1=Seconds()
Create Cursor 结果 (区间 C(20),和 N(8))
NSUM=0
Select 测试
Scan
    NSUM=NSUM+If Mod(序号,6)=0
        Insert Into 结果 Values (Transform(测试.序号-5)+"-"+Transform(测试.序号),NSUM)
        NSUM=0
    Endif
Endscan
? "方法2 共用时 "+Transform(Seconds()-T1)+" 秒"



T1=Seconds()
Select (序号 - 5) as 区间起, 序号 As 区间终, ;
    (2*- 5)*3 AsFrom 测试 Where Mod(序号, 6) = 0 Into Cursor ttt
?"方法3 共用时 "+Transform(Seconds()-T1)+" 秒"


T1=Seconds()
Create Cursor 结果2 (区间起 I, 区间终 I, 和 I)
NSUM=0
Select 测试
Scan
    NSUM = NSUM +If Mod(序号,6) != 0
        LOOP
    ENDIF
    INSERT INTO 结果2 VALUES (测试.序号-5, 测试.序号, NSUM)
    NSUM=0
Endscan
?"方法4 共用时 "+Transform(Seconds()-T1)+" 秒"
Return
2016-05-03 09:15
mywisdom88
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:191
帖 子:3147
专家分:8408
注 册:2015-3-25
收藏
得分:0 
以下是引用aaaaaa在2016-5-2 22:21:32的发言:

Close Databases

* 生成测试表
Create Cursor 测试 (序号 I,值 I)
NVAL=10000002
For I=1 To NVAL
    Insert Into 测试 Values (I,I)
Endfor

* 生成区间表
Create Cursor 区间 (X I,Y I,Z I)
J=0
For I=1 To Int(NVAL/6) Step 6
    J=J+1
    Insert Into 区间 Values (I,I+5,J)
Endfor



*!*    ================================================
*!*    不好意思,只快了 30% (快10+)秒。俺刘格艾还要努力
*!*    一条 SQL 查询语句,10,000,002(一千万条记录),SQL 的约20秒,VFP 的约 30秒

* 测试方法1_SQL
T1=Seconds()

Select Transform(序号 - 5) + "-" + Transform(序号) + Space(20) As 区间, ;
    (2*值 - 5)*3 As 和 From 测试 Where Mod(序号, 6) = 0 Into Cursor ttt

Messagebox("共用时 "+Transform(Seconds()-T1)+" 秒")
*!*    ================================================

Return


* 测试方法2_VFP

* 求和结果表
T1=Seconds()
Create Cursor 结果 (区间 C(20),和 N(8))
NSUM=0
Select 测试
Scan
    NSUM=NSUM+值
    If Mod(序号,6)=0
        Insert Into 结果 Values (Transform(测试.序号-5)+"-"+Transform(测试.序号),NSUM)
        NSUM=0
    Endif
Endscan
Messagebox("共用时 "+Transform(Seconds()-T1)+" 秒")
Select 结果
Browse

Return

* 测试方法1_SQL
T1=Seconds()

Select Transform(序号 - 5) + "-" + Transform(序号) + Space(20) As 区间, ;
    (2*值 - 5)*3 As 和 From 测试 Where Mod(序号, 6) = 0 Into Cursor ttt

Messagebox("共用时 "+Transform(Seconds()-T1)+" 秒")
*!*    ================================================

Return
AAAAAAAAAAAAAAAAAAA,运行这个查询,怎么会有进度条出来的,我看了你语句,好像没涉及到进度条阿。难道是数据很多的时候,自动出来的?
图片附件: 游客没有浏览图片的权限,请 登录注册
2016-05-03 09:39
baichuan
Rank: 7Rank: 7Rank: 7
等 级:贵宾
威 望:37
帖 子:953
专家分:589
注 册:2006-3-13
收藏
得分:0 
进来看一眼,怎么变成SQL和VFP之争了。。。。。。

2016-05-03 09:50
aaaaaa
Rank: 8Rank: 8
等 级:贵宾
威 望:21
帖 子:796
专家分:937
注 册:2012-9-4
收藏
得分:0 
以下是引用吹水佬在2016-5-3 08:17:57的发言:


从算法看,都是遍历一次就可搞定,两种方法差不多。
运行效率显然是SQL命令高,遍历循环体一个是编译指令,可直接放到指令寄存器执行;另一个是解释指令,要先解释成机器代码才可放到指令寄存器执行,显然循环次数越多,相对效率就越低。
有兴趣的可以这样测试:用编译语言(如ASM、C)写个扩展函数处理这个问题,提供给VFP调用,与用VFP代码的结果比较看看。


》》运行效率显然是SQL命令高

哈哈,吹领导挺会说安抚的话,温暖。
我们撇开谁好谁差有个人偏爱/成见的问题,但我们可以讨论优化或者适用的问题。

正宗的 SQL 语言是一个强大的数据库语言,是国际规范,包含了丰富的聚合运算、数理统计的函数。而 VFP 内部的 SQL 语言,是一种简单的、非规范的语言,而且功能差得远。
但不妨碍你学习 SQL,也没有与 VFP 的过程语言有任何利害冲突。他们是相辅相成的关系,不敌对的,何必排斥?

SQL Server/DB2/Oracle 等 SQL 都是可以异步的,或者多线程、多任务的。
但是,VFP 内部的 SQL Select DBF/Cursor 语句也可以非阻塞/异步的方式,Selece 后面加 NoWait 子句即可。
至少这个就是 SQL 不可放弃的一大优点/亮点。

不管是什么语言,都是工具,我们不要厚此薄彼。

俄罗斯轮盘赌一盘见输赢,有运气的成分,使人不服气的,但我们还是友谊为重,不 PK 了,怎样?
友谊之船说翻就翻,这样不好。S 老师永远是我的偶像。


民工子弟学校22班团小组长阳光模特队长冲锋篮球队前锋小苹果合唱队领唱蓝天舞蹈队编舞
2016-05-03 10:02
快速回复:指定区间求和
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.022967 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved