SQL查询统计:如何纳入空值,统计助学金对应全/兼职学期数
解决助学金学期统计的问题
看起来你的核心痛点是当前查询只统计了学生获得对应助学金的学期,完全漏掉了全时注册但没拿到该助学金的那些学期。咱们一步步修正这个逻辑:
问题拆解
你需要统计的是每个学生+每个助学金的两类学期总和:
- 所有全时注册(≥12学时)的学期,无论该学期是否获得该助学金
- 半时注册(1<学时<12)且该学期获得了该助学金的学期
当前查询的问题在于:通过TERM.TERM_CODE = AWARDS_TERM_CODE把范围限定在了学生拿该助学金的学期,自然无法覆盖全时但没拿助学金的学期。
修正后的SQL方案
我们需要先把学生的所有学期和所有助学金类型做关联,确保每个助学金都能覆盖学生的每一个学期,再按规则统计:
WITH student_terms AS ( -- 提取每个学生的所有注册学期,包含学时信息 SELECT ENROLLMENT_STUDENT_ID AS STUDENT_ID, ENROLLMENT_TERM_CODE AS TERM_CODE, ENROLLMENT_ENROLLED_HRS AS HRS_ENROLLED FROM ENROLLMENT ), student_unique_awards AS ( -- 提取每个学生的所有独特助学金类型(去重,避免重复计算) SELECT DISTINCT AWARDS_STUDENT_ID AS STUDENT_ID, AWARDS_FUND_CODE AS AWARD_CODE FROM AWARDS ), student_award_term_mapping AS ( -- 将每个学生的所有学期与所有助学金关联,标记该学期是否获得对应助学金 SELECT st.STUDENT_ID, sua.AWARD_CODE, st.TERM_CODE, st.HRS_ENROLLED, CASE WHEN EXISTS ( SELECT 1 FROM AWARDS a WHERE a.AWARDS_STUDENT_ID = st.STUDENT_ID AND a.AWARDS_TERM_CODE = st.TERM_CODE AND a.AWARDS_FUND_CODE = sua.AWARD_CODE ) THEN 1 ELSE 0 END AS has_award_this_term FROM student_terms st JOIN student_unique_awards sua ON st.STUDENT_ID = sua.STUDENT_ID ) -- 最终统计符合条件的学期数 SELECT STUDENT_ID, AWARD_CODE, SUM( CASE -- 条件1:全时注册的学期,直接计数 WHEN HRS_ENROLLED >= 12 THEN 1 -- 条件2:半时注册且该学期获得对应助学金,才计数 WHEN HRS_ENROLLED > 1 AND HRS_ENROLLED < 12 AND has_award_this_term = 1 THEN 1 ELSE 0 END ) AS AWARD_COUNT FROM student_award_term_mapping GROUP BY STUDENT_ID, AWARD_CODE ORDER BY STUDENT_ID, AWARD_CODE;
逻辑解释
- student_terms:获取所有学生的注册记录,确保不遗漏任何学期(哪怕该学期学生没拿任何助学金)。
- student_unique_awards:提取每个学生的所有助学金类型,去重是为了避免同一助学金被重复处理。
- student_award_term_mapping:这是关键一步——把学生的每个学期和每个助学金做关联,同时用
EXISTS判断该学期学生是否拿到了对应助学金。这样就确保了全时但没拿助学金的学期也能被纳入统计范围。 - 最后统计阶段,按照你的需求判断每个学期是否符合计数条件,求和得到最终结果。
匹配示例结果的小调整
看你的示例期望结果,AWARD_222的计数是10,其中包含了SUMMER_2019(学时1)的学期。这说明你的半时注册定义可能是≥1且<12(而不是1<学时<12)。如果是这样,只需要把CASE里的半时条件改成:
WHEN HRS_ENROLLED >= 1 AND HRS_ENROLLED < 12 AND has_award_this_term = 1 THEN 1
这样就能完全匹配你给出的期望结果了。
内容的提问来源于stack exchange,提问作者James M. Rodenbeck
相关产品推荐
相关产品推荐

