方法一,使用join做两表关联
with t as ( select a.uid uid1,exam_id,start_time,submit_time,score, case when score>=90 then '优' when score>=75 then '良' when score>=60 then '中' else '差' end as score_grade, `level` from exam_record a left join user_info b on a.uid=b.uid where submit_time is not null ) select `level1` `level`, score_grade,round(SUM(个数)/SUM(总个数),3) ratio from (select `level` `level1`, score_grade,count(*) 个数 from t group by `level`, score_grade) t1 inner join ( select `level`,count(*) 总个数 from t group by `level` ) t2 on t1.`level1`=t2.`level` group by `level1`, score_grade order by `level1` desc,ratio desc方法二: 使用开窗函数,count,在不改变表结构情况下,计数大小
select level, score_grade, round(count(*) / avg(total), 3) ratio from ( select bb.level, case when score >= 90 then '优' when score >= 75 then '良' when score >= 60 then '中' else '差' end score_grade, count(aa.uid) over(partition by level) total from exam_record aa join user_info bb on aa.uid=bb.uid where score is not null ) t1 group by level, score_grade order by level desc, ratio desc
开窗函数复习
rank() over() 1 2 2 4 4 6 (计数排名,跳过相同的几个,eg.没有3没有5)\row_number() over() 1 2 3 4 5 6 (赋予唯一排名)
dense_rank() over() 1 2 2 3 3 4 (不跳过排名,可以理解为对类别进行计数)
percent_rank() over() 按照数字所在的位置进行百分位分段
ntile(n)over() 将数字按照大小平均分成n段
lead(字段名,n)over()把字段数据向前移n个单元格
lag(字段名,n)over()把字段数据向后移n个单元格
last_value(字段名1) over (order by rows between unbounded preceding and unbounded following) 根据排序返回字段名1最后一行,也可以加上partition by 一起使用
frist_value(字段名2) over (order by rows between unbounded preceding and unbounded following) 根据排序返回字段名2第一行,也可以加上partition by 一起使用
5个常用的聚合窗口函数
min()over() :不改变表结构的前提下,计算出最小值
max()over():不改变表结构的前提下,计算出最大值
count()over():不改变表结构的前提下,计数
sum()over():不改变表结构的前提下,求和
avg()over():不改变表结构的前提下,求平均值