通过代码

SELECT
    level,
    score_grade,
    round(lei/tol,3) ratio
FROM
(SELECT
    level,
    score_grade,
    count(*)over(
        partition by level,score_grade
    ) lei,
    count(*)over(
        partition by level) tol
from(
SELECT
    user_info.uid,
    score,
    level,
    (case 
     when score between 0 and 59 then '差'
     when score between 60 and 74 then '中'
     when score between 75 and 89 then '良'
     when score between 90 and 100 then '优'
     end
    ) score_grade
FROM
    exam_record 
RIGHT JOIN
    user_info
ON
    exam_record.uid = user_info.uid
WHERE 
    score is not NULL
)e)t
GROUP BY
    level,score_grade
ORDER BY
    level desc,ratio DESC

思路

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

1.分数转化然后初步筛选出答过试卷的用户

2.窗口函数查出来相应count

3.计算相应数据并排序


分数转化然后初步筛选出答过试卷的用户

SELECT
    user_info.uid,
    score,
    level,
    (case 
     when score between 0 and 59 then '差'
     when score between 60 and 74 then '中'
     when score between 75 and 89 then '良'
     when score between 90 and 100 then '优'
     end
    ) score_grade
FROM
    exam_record 
RIGHT JOIN
    user_info
ON
    exam_record.uid = user_info.uid
WHERE 
    score is not NULL

窗口函数查出来相应count

SELECT
    level,
    score_grade,
    count(*)over(
        partition by level,score_grade
    ) lei,
    count(*)over(
        partition by level) tol
from(1.代码)e

计算相应数据排序

SELECT
    level,
    score_grade,
    round(lei/tol,3) ratio
FROM(2.代码)t
GROUP BY
    level,score_grade
ORDER BY
    level desc,ratio DESC

这样逻辑清晰,过程很容易理解,但是使用了三层子查询

我们可以考虑进行一个小优化也就是:

第一层就把总数给算出来,这样只需要两层就可以

通过代码2

SELECT
    level,
    score_grade,
    round(count(*)/tol,3) ratio
FROM
(SELECT
    user_info.uid,
    score,
    level,
    (case 
     when score between 0 and 59 then '差'
     when score between 60 and 74 then '中'
     when score between 75 and 89 then '良'
     when score between 90 and 100 then '优'
     end
    ) score_grade,
    count(*)over(
        partition by level) tol
FROM
    exam_record 
RIGHT JOIN
    user_info
ON
    exam_record.uid = user_info.uid
WHERE 
    score is not NULL
)t
GROUP BY
    level,score_grade
ORDER BY
    level desc,ratio DESC

如果第一次就group by会把数据综合,导致二次group的时候计数错误,所以这里用了窗口函数。