注册 登录
编程论坛 VFP论坛

各位大侠,使用SQL语句能否一次性取得各班成绩前20%的学生的信息

schtg 发布于 6 天前 18:17, 572 次点击
各位大侠,现有一表,能否使用SQL语句一次性取得 各班 成绩从高到低的前20%的学生的信息(单独按班分别获取,可以办到),谢谢!
只有本站会员才能查看附件,请 登录
18 回复
#2
kangss6 天前 18:38
以下是引用schtg在2025-12-13 18:17:16的发言:

各位大侠,现有一表,能否使用SQL语句一次性取得 各班 成绩从高到低的前20%的学生的信息(单独按班分别获取,可以办到),谢谢!

试了半天,一行语句不成功,因为SQL只要加了“TOP 20%”,就已经不能把其他班级查询出来。
#3
吹水佬6 天前 18:55
算出20%是多少条记录,有个问题是相同成绩的怎计数?
#4
schtg6 天前 18:56
回复 3楼 吹水佬
相同成绩计算在内,要算上的哈。我是要取出各班成绩的前20%的学生的信息,包括姓名、班级、成绩等数据,谢谢!

[此贴子已经被作者于2025-12-13 18:58编辑过]

#5
schtg6 天前 18:56
回复 2楼 kangss
我也是试了很久,都没有搞定的,谢谢!
#6
吹水佬6 天前 19:11
是不是这意思:有120个学生,取前20%就是前24个。
#7
schtg6 天前 19:12
回复 6楼 吹水佬
按班来取,比如1班有55个学生,那么就取前11名,2班有60个学生,那么就取前12名,以此类推。
#8
吹水佬6 天前 21:12
以下是引用schtg在2025-12-13 19:12:59的发言:

按班来取,比如1班有55个学生,那么就取前11名,2班有60个学生,那么就取前12名,以此类推。

CREATE CURSOR tt (f1 I, f2 I)
FOR i=1 TO 100
    INSERT INTO tt VALUES (i,i*2)
ENDFOR
SELECT TOP (RECCOUNT()*0.2) * FROM tt ORDER BY f1 DESC
#9
schtg5 天前 05:53
回复 8楼 吹水佬
吹版主,这就是一个班中取前20%的情形,我需要的是一个自由表中 一次性 获取 5个班、或10个班、或更多班级的总分前20%的学生的信息,不是一个班一个班的获取,谢谢!
#10
my23185 天前 07:38
个人理解,60人的班级,前20%应该是成绩高于或等于第12名成绩的集合,返回人数应该多于或等于12 人,能否一次取回多班结构,取决于数据表结构,平板上打不开附件,不好臆断
#11
吹水佬5 天前 08:14
回复 9楼 schtg
我只是一个算法,具体数据按实际情况去组织,按班算就算 班的记录数*20%


#12
吹水佬5 天前 08:18
回复 10楼 my2318
3楼提到的问题,如果20%中最后一个与跟随其后面的一个成绩相同就有问题。
#13
schtg5 天前 19:47
我知道基本上只能先分班获取再合成一个新表,谢谢各位!
#14
yiyanxiyin5 天前 19:49
SELECT
    s1.class_id,
    s1.student_id,
    s1.student_name,
    s1.score
FROM students s1
WHERE (
    -- 计算比当前学生成绩高的同班学生数
    SELECT COUNT(*)
    FROM students s2
    WHERE s2.class_id = s1.class_id
      AND s2.score > s1.score
) < (
    -- 计算班级总人数的20%(向上取整)
    SELECT CEIL(COUNT(*) * 0.2)
    FROM students s3
    WHERE s3.class_id = s1.class_id
)
ORDER BY s1.class_id, s1.score DESC;
看看这个思路
#15
schtg5 天前 19:55
回复 14楼 yiyanxiyin
谢谢!试一试哈。
#16
chychychy4 天前 10:13
想法是先按班级排名,再计算班级总人数的20%,取班级排名小于这个数字的。新手的语句有点啰嗦,就当抛砖引玉吧
参考自:编程论坛 - 求助:SQL语句
https://bbs.
程序代码:

* 增加一个bjmc字段,记录班级排名
SELECT *,00000 AS bjmc FROM stu INTO CURSOR temp1 READWRITE
UPDATE temp1 SET bjmc=(SELECT COUNT(*)+1 FROM temp1 AS B WHERE B.成绩>temp1.成绩 AND B.班级=temp1.班级)

* 生成班级人数总人数和前百分20 人数统计表。

SELECT 班级, COUNT(*) AS zrs, ;
        CEILING(COUNT(*) * 0.2) AS ncount20 ;
FROM stu ;
WHERE NOT EMPTY(班级) ;
GROUP BY 班级 ;
INTO CURSOR tempbj

BROWSE &&& 测试查看用

* 创建空临时表结构
SELECT * FROM temp1 ;
    WHERE .F. ;
    INTO CURSOR TEMP2 READWRITE

* 循环处理每个班级,直接使用tempbj表统计的数值
SELECT tempbj
SCAN
* 从tempbj中直接获取总人数和前百分之20人数。
    nCount = tempbj.zrs
    nCount20 = tempbj.ncount20

* 取前百分之20的学生
    SELECT * FROM temp1 ;
        WHERE (temp1.班级) = (tempbj.班级) ;
        AND NOT EMPTY(班级) ;
        AND bjmc <= nCount20 ;  && 排名小于等于前20%的人数
        ORDER BY 成绩 DESC ;
        INTO ARRAY bjzf

* 追加到临时表
    SELECT TEMP2
    APPEND FROM ARRAY bjzf
ENDSCAN

* 显示结果
SELECT TEMP2
GO TOP
BROWSE &&& 测试查看用




[此贴子已经被作者于2025-12-15 14:16编辑过]

#17
schtg4 天前 12:31
回复 16楼 chychychy
非常感谢!
#18
chychychy4 天前 15:29
回复 16楼 chychychy
数据量一大速度就慢了,从9000多记录里面找,大约3.7秒(vfp9.0 sp1;win10;Intel(R) Core(TM) i5-10500 CPU @ 3.10GHz )
只有本站会员才能查看附件,请 登录

程序代码:

**2025年12月15日,整理测试
**来自:编程论坛 - 各位大侠,使用SQL语句能否一次性取得各班成绩前20%的学生的信息
**https://bbs.bc-/viewthread.php?tid=514644&page=2&extra=page%3D1#pid2795494
t1=Seconds()&&计时函数
** 增加一个bjmc字段,记录班级排名
SELECT *,00000 AS bjmc FROM zcj INTO CURSOR temp1 READWRITE
UPDATE temp1 SET bjmc=(SELECT COUNT(*)+1 FROM temp1 AS B WHERE B.zcj>temp1.zcj AND B.bj=temp1.bj)

** 生成bj人数总人数和前百分20人数统计表。

SELECT bj, COUNT(*) AS zrs, ;
    CEILING(COUNT(*) * 0.2) AS nCount20 ;
    FROM zcj ;
    WHERE NOT EMPTY(bj) ;
    GROUP BY bj ;
    INTO CURSOR tempbj

*BROWSE TITLE "bj总人数和前百分之20人数"  &&& 测试查看用

* 创建空临时表结构
SELECT * FROM temp1 ;
    WHERE .F. ;
    INTO CURSOR TEMP2 READWRITE

* 循环处理每个bj,直接使用tempbj表统计的数值
SELECT tempbj
SCAN
* 从tempbj中直接获取总人数和前百分之20人数。
    nCount = tempbj.zrs
    nCount20 = tempbj.nCount20

* 取前百分之20的学生
    SELECT * FROM temp1 ;
        WHERE (temp1.bj) = (tempbj.bj) ;
        AND NOT EMPTY(bj) ;
        AND bjmc <= nCount20 ;  && 排名小于等于前20%的人数
    ORDER BY zcj DESC ;
        INTO ARRAY bjzf

* 追加到临时表
    SELECT TEMP2
    APPEND FROM ARRAY bjzf
ENDSCAN

Messagebox("完成!共运行:"+Transform(Seconds()-t1)+"秒",64, "计时信息") &&计算用时多少
* 显示结果
SELECT TEMP2
GO TOP
BROWSE &&& 测试查看用
#19
schtg4 天前 15:40
回复 18楼 chychychy
辛苦啦,非常感谢!
1