如何动态生成目标输出?基于双学生表的成绩百分比计算与按分数段、性别分组统计问题
解决学生成绩分数段按性别分组统计的问题
看起来你遇到了两个核心问题:一是存储过程的分组逻辑错误,导致统计的是科目相关数据而非分数段的学生数量;二是没有预设所有分数段的基准列表,因此无学生的分数段无法显示。下面是修正后的完整方案:
修正后的存储过程代码
create or alter proc student_avg_marks as begin -- 第一步:生成所有需要的分数段列表,确保空区间也能显示 with ScoreRanges as ( select 'Below 25%' as score_range union all select '25% - 50%' union all select '50% - 75%' union all select 'Above 75%' ), -- 第二步:计算每个学生的平均成绩,并关联性别信息 StudentAvgScores as ( select sd.student_gender, case when avg(sm.marks) < 25 then 'Below 25%' when avg(sm.marks) between 25 and 50 then '25% - 50%' when avg(sm.marks) between 50 and 75 then '50% - 75%' else 'Above 75%' end as score_range from student_details sd inner join student_marks sm on sd.id = sm.student_id group by sd.id, sd.student_gender -- 按学生ID分组,确保每个学生只计算一次平均成绩 ) -- 第三步:关联分数段列表,统计各区间的学生数、男女生人数 select sr.score_range as avg_marks, count(sas.student_gender) as [total no. of students], sum(case when sas.student_gender = 'Male' then 1 else 0 end) as male_count, sum(case when sas.student_gender = 'Female' then 1 else 0 end) as female_count from ScoreRanges sr left join StudentAvgScores sas on sr.score_range = sas.score_range group by sr.score_range order by case sr.score_range -- 按分数段顺序排序 when 'Below 25%' then 1 when '25% - 50%' then 2 when '50% - 75%' then 3 when 'Above 75%' then 4 end end
关键改动说明
- 预设分数段列表:通过CTE
ScoreRanges生成所有需要显示的分数段,后续用左连接确保即使无学生的区间也会出现在结果中。 - 正确计算学生平均成绩:在
StudentAvgScores中按sd.id(学生ID)分组,确保每个学生的平均成绩只计算一次,避免原代码中按科目分组的错误。 - 左连接统计:用分数段列表左连接学生平均成绩数据,保证所有分数段都被统计,无学生的区间会显示0值。
- 有序输出:通过
order by的case语句让结果按分数段的逻辑顺序排列,更符合阅读习惯。
测试结果
执行你的测试数据后,存储过程会输出如下结果:
| avg_marks | total no. of students | male_count | female_count |
|---|---|---|---|
| Below 25% | 0 | 0 | 0 |
| 25% - 50% | 1 | 1 | 0 |
| 50% - 75% | 1 | 0 | 1 |
| Above 75% | 0 | 0 | 0 |
完全符合你需要的统计要求,即使无学生的分数段也会显示,且人数统计准确。
内容的提问来源于stack exchange,提问作者Manas Ind
相关产品推荐
相关产品推荐

