SQL41 各用户等级的不同得分表现占比

题目主要信息:

  • 将试卷得分按分界点 [90, 75, 60] 分为优良中差四个得分等级(分界点划分到左区间)
  • 统计不同用户等级的人在完成过的试卷中各得分等级占比(结果保留3位小数)
  • 未完成过试卷的用户无需输出

问题拆解:

  • 通过 CASE 语句将 exam_record 中的 score 映射为优良中差四个得分等级,并保留 uid, level 信息。CASE 语句具有两种格式:简单 CASE 函数和 CASE 搜索函数。此处使用 CASE 搜索函数,从低到高筛选出符合要求的等级。知识点:CASE
    • CASE 搜索函数语法为 CASE WHEN {stat_1} THEN {res_1} WHEN {stat_2} THEN {res_2} ... ELSE {default} END
  • 使用 COUNT OVER 语句统计出每个 level 完成试卷的总数。首先需要通过 WHERE 语句筛选出 submit_time 非空的数据,在统计试卷总数时需要用 PARTITION BY 指定聚合口径为 level。知识点:COUNT, OVER, PARTITION
  • 以 WITH AS 语句将上述数据存储为临时表供接下来使用
  • 对上述数据基于 level 和 分数等级 进行聚合统计,为了获取每个等级占比,需要用 COUNT(1) 统计出 level x grade 的出现次数,并对之前统计出的 level 维度试卷总数做除法。知识点:COUNT, GROUP BY
  • 用 ROUND 函数对每个用户等级回答的试卷中,各得分等级的占比取三位小数,语法为 ROUND(val, 3),结果按照 level 降序(ORDER BY level DESC) 得分等级占比 降序 输出。知识点:ROUND, ORDER BY, DESC

代码:

WITH grade AS (
    SELECT user_info.uid, level, CASE
            WHEN exam_record.score < 60 THEN '差'
            WHEN exam_record.score < 75 THEN '中'
            WHEN exam_record.score < 90 THEN '良'
            ELSE '优'
        END AS score_grade,
        COUNT(1) OVER(PARTITION BY level) AS lvl_cnt
    FROM exam_record
    LEFT JOIN user_info
    ON exam_record.uid = user_info.uid
    WHERE exam_record.submit_time IS NOT NULL
)
SELECT
    level,
    score_grade,
    ROUND(COUNT(1) / AVG(lvl_cnt), 3)
FROM grade
GROUP BY level, score_grade
ORDER BY level DESC, COUNT(1) / AVG(lvl_cnt) DESC