| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4225 人关注过本帖, 1 人收藏
标题:不同分数段人数统计的简易方法
只看楼主 加入收藏
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
隨便說個例子吧,代碼裡面出現了具體的、數目有限的科目名稱,而當設計的數據表科目有增減或名稱變動時,就要改代碼了,這叫硬編碼。後面那一堆UPDATE,就是很明顯的微小差別語句重複,很礙眼的。

授人以渔,不授人以鱼。
2014-03-18 19:25
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
再說一個不是硬編碼的問題,還是那一堆UPDATE,是分別處理每個字段,但這樣一來就是把數據表反復掃描了UPDATE語句次數那麽多次,效率很低的,對這種情況,應該僅掃描一次,在每條記錄上REPLACE相應的字段,需知讀入一條記錄橫向掃描所佔用的內存比縱向讀入整個數據表(因爲這種UPDATE SET相當於REPALCE ALL循環,讀入一條記錄要把整個記錄載入內存,哪怕僅處理一個字段即一個單元格)來得少及速度快得多。

[ 本帖最后由 TonyDeng 于 2014-3-18 19:34 编辑 ]

授人以渔,不授人以鱼。
2014-03-18 19:32
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:335
帖 子:9816
专家分:27071
注 册:2012-2-5
收藏
得分:0 
听君一席话,胜读十年书。
我再看看

坚守VFP最后的阵地
2014-03-18 20:12
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:335
帖 子:9816
专家分:27071
注 册:2012-2-5
收藏
得分:0 
以下是引用TonyDeng在2014-3-18 19:25:53的发言:

隨便說個例子吧,代碼裡面出現了具體的、數目有限的科目名稱,而當設計的數據表科目有增減或名稱變動時,就要改代碼了,這叫硬編碼。後面那一堆UPDATE,就是很明顯的微小差別語句重複,很礙眼的。
这个问题我也考虑过了,先写出代码,再修改为相对通用的代码。

坚守VFP最后的阵地
2014-03-18 20:17
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
是的,慢慢改。

授人以渔,不授人以鱼。
2014-03-18 20:22
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:335
帖 子:9816
专家分:27071
注 册:2012-2-5
收藏
得分:0 
CJ.rar (10.88 KB)

再版

程序代码:
SET TALK OFF
*-创建一个分数段标准表,这个标准表可以是自由表,也可以是临时表
CREATE CURSOR bz (下限 N(3),上限 N(3))
NUM=10 && 10分一个分数段,或者手工建一个自由表,前提是分数必须为整数
FSD=80 && 按照总成绩的满分设置分数段,共设置FSD个分数段
FOR I=1 TO FSD
    IF I=1
       INSERT INTO BZ VALUES (0,NUM-I)
    ELSE
       INSERT INTO BZ VALUES (NUM1+1,NUM1+NUM)
    ENDIF
    NUM1=上限
ENDFOR

* 统一格式,便于统计(列记录转换为行记录),获取字段数,表中各门功课成绩排在所有非成绩字段的后面
SELECT * FROM CJ INTO CURSOR CJ1
NZDS=AFIELDS(AZDM,[CJ1])
CSQL=[]
FOR I=2 TO NZDS && 本示例中,从第2个字段开始为各门课程的成绩字段
    CSQL=CSQL+IIF(I>2,[UNION ALL ],[])+[SELECT 班级,']+AZDM[I,1]+[' 课程,]+AZDM[I,1]+[ 成绩]+[,' ]+SPACE(7)+[' 分数段 FROM CJ ]+IIF(I=NZDS,[INTO CURSOR CJ2 READWRITE],[])
ENDFOR
* 执行SQL命令
EXECSCRIPT(CSQL)

* 划分分数段
UPDATE CJ2 SET 分数段=PADL(BZ.下限,3,[0])+[-]+PADL(BZ.上限,3,[0]) FROM BZ WHERE BETWEEN(CJ2.成绩,BZ.下限,BZ.上限)

* 统计不同分数段(按课程分)的人数
SELECT 班级,课程,分数段,COUNT(*) 人数 FROM CJ2 GROUP BY 1,2,3 INTO CURSOR CJ3

* 生成不同班级,不同课程的分数段
SELECT A.*,PADL(B.下限,3,[0])+[-]+PADL(B.上限,3,[0]) 分数段 FROM (SELECT 班级,课程 FROM CJ3 GROUP BY 1,2) A,BZ B INTO CURSOR BJKC

* 填补每门课程不存在的分数段
SELECT A.班级,A.课程,A.分数段,NVL(B.人数,0) 人数 FROM BJKC A LEFT JOIN CJ3 B ON A.分数段=B.分数段 AND A.班级=B.班级 AND A.课程=B.课程 INTO CURSOR CJ4

* 生成分数段最后统计表(行记录转换为列记录)
SELECT 课程 FROM CJ3 GROUP BY 1 INTO CURSOR KC
CSQL="SELECT 班级,分数段"
SCAN
   CSQL=CSQL+",CAST(SUM(IIF(ALLTRIM(课程)=='"+ALLTRIM(课程)+"',人数,0)) AS N(4)) AS "+ALLTRIM(课程)+;
    IIF(RECNO()<RECCOUNT(),[],[,0000 小计 FROM CJ4 GROUP BY 1,2 INTO CURSOR CJTJB READWRITE])
ENDSCAN
EXECSCRIPT(CSQL)

* 行记录计算
XJ=[]
FOR I=3 TO FCOUNT()-2 && 从第三个字段开始统计行记录小计,最后两个字段分别是 总分、小计 字段
    XJ=XJ+(FIELD(I))+IIF(I<FCOUNT()-2,[+],[])
ENDFOR
REPLACE ALL [小计] WITH &XJ

* 列记录计算
NZDS=AFIELDS(AZDM,[CJTJB])
CSQL=[SELECT ALLTRIM(班级)+'合' 班级,SPACE(7) 分数段]
SET ENGINEBEHAVIOR 70
FOR I=3 TO NZDS
   CSQL=CSQL+",CAST(SUM("+AZDM[I,1]+") AS N(4)) AS "+AZDM[I,1]+IIF(I<NZDS," "," FROM CJTJB GROUP BY 班级")
ENDFOR
CSQL=[INSERT INTO CJTJB ]+CSQL
EXECSCRIPT(CSQL)
SELECT * FROM CJTJB ORDER BY 1 INTO CURSOR CJTJ READWRITE
FOR I=3 TO FCOUNT()
    IF TYPE(FIELD(I))="N"
       *--- 清空数值型字段内容为"0"的记录
       BLANK FIELD (FIELD(I)) FOR EVALUATE(FIELD(I))=0
    ENDIF
ENDFOR
BROWSE
SET ENGINEBEHAVIOR 90


[ 本帖最后由 sdta 于 2014-3-19 00:54 编辑 ]

坚守VFP最后的阵地
2014-03-18 23:51
小主板
Rank: 2
等 级:论坛游民
帖 子:187
专家分:21
注 册:2009-6-28
收藏
得分:0 
厉害!!!!!!
2014-03-20 20:44
sylknb
Rank: 4
等 级:贵宾
威 望:14
帖 子:1530
专家分:180
注 册:2006-6-3
收藏
得分:0 
sdta班主
按你第一次的代码运行数据表,发现TOT1<100(17,18,19,52....)分段时变成10--109了,不知何故?附下原表及FSD
FSD.rar (574 Bytes)
bk.rar (27.48 KB)
图片附件: 游客没有浏览图片的权限,请 登录注册
2014-03-21 10:07
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:335
帖 子:9816
专家分:27071
注 册:2012-2-5
收藏
得分:0 
按最后一次代码运行

坚守VFP最后的阵地
2014-03-21 10:35
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:335
帖 子:9816
专家分:27071
注 册:2012-2-5
收藏
得分:0 
回复 28楼 sylknb
按照你的实际情况,代码如下
程序代码:
CREATE CURSOR BZ (下限 N(3),上限 N(3))
NUM=10 && 10分一个分数段,或者手工建一个自由表,前提是分数必须为整数
FSD=80 && 按照总成绩的满分设置分数段,共设置FSD个分数段
FOR I=1 TO FSD
    IF I=1
       INSERT INTO BZ VALUES (0,NUM-I)
    ELSE
       INSERT INTO BZ VALUES (NUM1+1,NUM1+NUM)
    ENDIF
    NUM1=上限
ENDFOR
SELECT XH,TOT1,SPACE(7) 分数段 FROM BK INTO CURSOR T1 READWRITE
UPDATE T1 SET 分数段=PADL(BZ.下限,3,[0])+[-]+PADL(BZ.上限,3,[0]) FROM BZ WHERE BETWEEN(T1.TOT1,BZ.下限,BZ.上限)
SELECT 分数段,COUNT(*) 人数 FROM T1 GROUP BY 分数段 INTO CURSOR T2
SELECT PADL(BZ.下限,3,[0])+[-]+PADL(BZ.上限,3,[0]) 分数段,NVL(人数,0) 人数 FROM BZ LEFT JOIN T2 ON PADL(BZ.下限,3,[0])+[-]+PADL(BZ.上限,3,[0])=T2.分数段 INTO CURSOR T3 READWRITE
INSERT INTO T3 SELECT [合计],SUM(人数) FROM T3
BROWSE


坚守VFP最后的阵地
2014-03-21 12:28
快速回复:不同分数段人数统计的简易方法
数据加载中...
 
   



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

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