注册 登录
编程论坛 VFP论坛

请帮忙排序

schtg 发布于 2023-03-19 10:44, 2768 次点击
通过SQL语句可以完成排序:
update xqpx set lkpx = (select count(a.dwbm)+1 from xqpx as a where a.jf>xqpx.jf and a.xk==xqpx.xk)  && 学科均分jf  从高到低  通排
update xqpx set bspx = (select count(a.dwbm)+1 from xqpx as a where a.jf>xqpx.jf and a.xk==xqpx.xk and a.dsmc==xqpx.dsmc)  && 学科均分jf 按市 从高到低 排序
【新】测试数据:
只有本站会员才能查看附件,请 登录

(虚拟数据中包含30个地市、每个地市包含20个县、每个县包含13所学校,有9个学科,共计70200条记录)
其中,地市名称dsmc、县区名称xqmc、学校名称xxmc、学科xk(拼音代替汉字)、均分jf、联考排序lkpx(按学科均分通排)、本市排序bspx(以学科均分按地市排序)、本县排序(以学科均分按县排序)。
应该还有更快、更好的排序方法,请大侠帮忙,谢谢!

[此贴子已经被作者于2023-3-19 18:07编辑过]

37 回复
#2
sdta2023-03-19 10:51
INDEX、SORT 试过吗

[此贴子已经被作者于2023-3-19 10:52编辑过]

#3
schtg2023-03-19 10:51
回复 2楼 sdta
没有哦。希望更快一点,哈哈^_^
#4
sdta2023-03-19 10:53
多少数据?要多快?
#5
schtg2023-03-19 10:55
回复 4楼 sdta
这是部分数据,全部记录超过1W5的哦。
#6
sdta2023-03-19 11:02
这点数据没办法测试
#7
吹水佬2023-03-19 11:07
数据结构合理,3几W的记录随便也差不多。
#8
laowan0012023-03-19 11:10
楼主目前的方法1W5排序大概需要多少秒?
#9
schtg2023-03-19 13:53
回复 8楼 laowan001
哈哈^_^,5秒以内吧。
#10
schtg2023-03-19 13:54
回复 7楼 吹水佬
就是希望快一点,语句能否再优化一下,谢谢!
#11
schtg2023-03-19 13:55
回复 6楼 sdta
主要研究一下算法哈,确实数据量偏少。
#12
schtg2023-03-19 13:56
回复 7楼 吹水佬
请问如何优化结构,使之更合理?谢谢!
#13
sdta2023-03-19 14:13
上传的这点数据,最多1秒
#14
schtg2023-03-19 17:56
回复 13楼 sdta
测试数据:
只有本站会员才能查看附件,请 登录
(虚拟数据中包含30个地市、每个地市包含20个县、每个县包含13所学校,有9个学科,共计70200条记录)
其中,地市名称dsmc、县区名称xqmc、学校名称xxmc、学科xk(拼音代替汉字)、均分jf、联考排序lkpx(按学科均分通排)、本市排序bspx(以学科均分按地市排序)、本县排序(以学科均分按县排序)。谢谢!

[此贴子已经被作者于2023-3-19 18:06编辑过]

#15
sdta2023-03-19 18:03
是排序还是排名次,具体要求是什么
#16
schtg2023-03-19 18:07
回复 15楼 sdta
排名哈(现在一般不说排名,改为排序,哈哈^_^),我没有说清楚,相同分数相同名次,联考排序lkpx(按学科均分通排)、本市排序bspx(以学科均分按地市排序)、本县排序(以学科均分按县排序)谢谢!

[此贴子已经被作者于2023-3-19 18:09编辑过]

#17
sdta2023-03-19 18:31
排名规则是:12225 还是12223?
#18
schtg2023-03-19 18:50
回复 17楼 sdta
排名规则是:12225,谢谢!
#19
sdta2023-03-19 22:34
程序代码:
CLOSE DATABASES
SET COLLATE TO "MACHINE"
* 联考名次
SELECT * FROM xqpx ORDER BY xk, jf DESC INTO CURSOR temp READWRITE
BLANK FIELDS lkpx ALL
lcxk = SPACE(0) && 学科
lnjf = 0 && 均分
lnmc = 1 && 名次
lnrs = 0 && 记录全部同科人数
SCAN
    lnrs = lnrs + 1
    IF xk == lcxk
        IF jf = lnjf
        ELSE
            lnmc = lnrs
        ENDIF
    ELSE
        lnmc = 1
        lnrs = 1
    ENDIF
    REPLACE lkpx WITH lnmc
    lcxk = xk
    lnjf = jf
    lnmc = lkpx
ENDSCAN
* 同市同科名次
SELECT * FROM temp ORDER BY dsmc,xk, jf DESC INTO CURSOR temp READWRITE
BLANK FIELDS bspx ALL
lcxk = SPACE(0) && 学科
lnjf = 0 && 均分
lnmc = 1 && 名次
lnrs = 0 && 记录本市同科人数
lcbs = SPACE(0) && 地市名称
SCAN
    lnrs = lnrs + 1
    IF dsmc == lcbs AND xk == lcxk
        IF jf = lnjf
        ELSE
            lnmc = lnrs
        ENDIF
    ELSE
        lnmc = 1
        lnrs = 1
    ENDIF
    REPLACE bspx WITH lnmc
    lcxk = xk
    lnjf = jf
    lnmc = bspx
    lcbs = dsmc
ENDSCAN
* 同县同科名次
SELECT * FROM temp ORDER BY xqmc,xk, jf DESC INTO CURSOR temp READWRITE
BLANK FIELDS bxpx ALL
lcxk = SPACE(0) && 学科
lnjf = 0 && 均分
lnmc = 1 && 名次
lnrs = 0 && 记录本县同科人数
lcbx = SPACE(0) && 县名称
SCAN
    lnrs = lnrs + 1
    IF xqmc == lcbx AND xk == lcxk
        IF jf = lnjf
        ELSE
            lnmc = lnrs
        ENDIF
    ELSE
        lnmc = 1
        lnrs = 1
    ENDIF
    REPLACE bxpx WITH lnmc
    lcxk = xk
    lnjf = jf
    lnmc = bxpx
    lcbx = xqmc
ENDSCAN
BROWSE


[此贴子已经被作者于2023-3-19 22:36编辑过]

#20
sdta2023-03-19 22:47
运行时间 <1.5s
#21
schtg2023-03-20 05:42
回复 20楼 sdta
@sdta,非常感谢!通过分段人数和累计人数确定排名,这就很快的,谢谢!
#22
丁春秋yxp2023-03-20 22:02
以下是引用sdta在2023-3-19 22:34:07的发言:

CLOSE DATABASES
SET COLLATE TO "MACHINE"
* 联考名次
SELECT * FROM xqpx ORDER BY xk, jf DESC INTO CURSOR temp READWRITE
BLANK FIELDS lkpx ALL
lcxk = SPACE(0) && 学科
lnjf = 0 && 均分
lnmc = 1 && 名次
lnrs = 0 && 记录全部同科人数
SCAN
    lnrs = lnrs + 1
    IF xk == lcxk
        IF jf = lnjf
        ELSE
            lnmc = lnrs
        ENDIF
    ELSE
        lnmc = 1
        lnrs = 1
    ENDIF
    REPLACE lkpx WITH lnmc
    lcxk = xk
    lnjf = jf
    lnmc = lkpx
ENDSCAN
* 同市同科名次
SELECT * FROM temp ORDER BY dsmc,xk, jf DESC INTO CURSOR temp READWRITE
BLANK FIELDS bspx ALL
lcxk = SPACE(0) && 学科
lnjf = 0 && 均分
lnmc = 1 && 名次
lnrs = 0 && 记录本市同科人数
lcbs = SPACE(0) && 地市名称
SCAN
    lnrs = lnrs + 1
    IF dsmc == lcbs AND xk == lcxk
        IF jf = lnjf
        ELSE
            lnmc = lnrs
        ENDIF
    ELSE
        lnmc = 1
        lnrs = 1
    ENDIF
    REPLACE bspx WITH lnmc
    lcxk = xk
    lnjf = jf
    lnmc = bspx
    lcbs = dsmc
ENDSCAN
* 同县同科名次
SELECT * FROM temp ORDER BY xqmc,xk, jf DESC INTO CURSOR temp READWRITE
BLANK FIELDS bxpx ALL
lcxk = SPACE(0) && 学科
lnjf = 0 && 均分
lnmc = 1 && 名次
lnrs = 0 && 记录本县同科人数
lcbx = SPACE(0) && 县名称
SCAN
    lnrs = lnrs + 1
    IF xqmc == lcbx AND xk == lcxk
        IF jf = lnjf
        ELSE
            lnmc = lnrs
        ENDIF
    ELSE
        lnmc = 1
        lnrs = 1
    ENDIF
    REPLACE bxpx WITH lnmc
    lcxk = xk
    lnjf = jf
    lnmc = bxpx
    lcbx = xqmc
ENDSCAN
BROWSE

大佬电脑什么配置,这么快
#23
sdta2023-03-20 22:22
配置情况
只有本站会员才能查看附件,请 登录
#24
qqln2023-03-21 06:13
不是电脑配置的问题,肯定是写错了,不是1.5s,应该是1.5m
#25
schtg2023-03-21 06:29
回复 24楼 qqln
可以验证的,确实小于1.5秒的哈。
只有本站会员才能查看附件,请 登录


[此贴子已经被作者于2023-3-21 06:53编辑过]

#26
qqln2023-03-21 06:40
用70200条纪录的表?我怎么不行呢?
#27
schtg2023-03-21 06:47
回复 26楼 qqln
用vfp9吧
#28
qqln2023-03-21 06:50
用的是vfp9
#29
schtg2023-03-21 06:56
回复 26楼 qqln
不行的意思是不能运行?还是耗时更多?哈哈^_^
#30
qqln2023-03-21 06:59
回复 29楼 schtg
能运行,但大于1m
#31
schtg2023-03-21 07:17
回复 30楼 qqln
首行加上:set talk off  再试一下哈。
#32
qqln2023-03-21 07:19
回复 31楼 schtg
这样速度差不多了
#33
csyx2023-03-21 07:42
sql-update 花的时间应该也差不多,至少一个数量级,只是你一楼的代码把一个O(1)复杂度的算法,活生生的写成了O(2)
#34
csyx2023-03-21 08:05
试试这段sql在你的电脑上花多少时间,我这本本上大概也1.5秒,服务器上就秒出结果
三段排名算法一模一样,唯一不同的是 group by 多一个字段,更新回源表时 join on 连接条件也同样多一个字段
程序代码:
Close Databases
Clear
Use xqpx Exclusive

ss = Seconds()
*-- 联考排名
Select xk, jf, Cast(0 as I) rank ;
    from xqpx group by xk,jf order by xk,jf desc into cursor temp1 readwrite
Update temp1 set rank = Recno()
Select xk, Min(rank) as rank from temp1 group by xk into cursor temp2
Update t set t.rank = 1 + t.rank - s.rank from temp1 t inner join temp2 s on t.xk == s.xk
Update t set t.lkpx = s.rank from xqpx t inner join temp1 s on t.jf == s.jf

*-- 地市排名
Select dsmc, xk, jf, Cast(0 as I) rank ;
    from xqpx group by dsmc,xk,jf order by dsmc,xk,jf desc into cursor temp1 readwrite
Update temp1 set rank = Recno()
Select dsmc, xk, Min(rank) as rank from temp1 group by dsmc,xk into cursor temp2
Update t set t.rank = 1 + t.rank - s.rank ;
    from temp1 t inner join temp2 s on t.xk == s.xk and t.dsmc == s.dsmc
Update t set t.bspx = s.rank ;
    from xqpx t inner join temp1 s on t.jf == s.jf and t.xk == s.xk and t.dsmc == s.dsmc

*-- 县区排名
Select dsmc, xqmc, xk, jf, Cast(0 as I) rank ;
    from xqpx group by dsmc,xqmc,xk,jf order by dsmc,xqmc,xk,jf desc into cursor temp1 readwrite
Update temp1 set rank = Recno()
Select dsmc, xqmc, xk, Min(rank) as rank from temp1 group by dsmc,xqmc,xk into cursor temp2
Update t set t.rank = 1 + t.rank - s.rank from temp1 t ;
    inner join temp2 s on t.xk == s.xk and t.dsmc == s.dsmc and t.xqmc == s.xqmc
Update t set t.bxpx = s.rank ;
    from xqpx t inner join temp1 s ;
    on t.jf == s.jf and t.xk == s.xk and t.dsmc == s.dsmc and t.xqmc == s.xqmc

Use in temp2
Use in temp1
Wait window nowait noclear '耗时:' + Transform(Seconds()-ss)

Select xqpx
Locate
Browse


[此贴子已经被作者于2023-3-21 08:09编辑过]

#35
schtg2023-03-22 05:46
回复 34楼 csyx
试一试哈,谢谢!
#36
schtg2023-03-22 05:50
回复 34楼 csyx
我在电脑上测试了一下,比sdta的要稍慢一点哈。谢谢你的指点!
#37
wxzd1232023-03-23 07:25
#38
chychychy2024-08-24 09:27
回复 31楼 schtg
(留个脚印学习了)加上这句快了相当多,0.493秒/47.21秒,可是中间也没弹出覆盖文件的提示呀?
1