【思路】
  1. 按tag统计2021年上半年的完成数,排名情况,作为表t1
  2. 按tag统计2021年上半年的完成数,排名情况,作为表t2
  3. t1 inner join t2 using(tag)关联出20上半年和21上半年都有作答的tag
  4. 基于t1和t2,再外层嵌一层查询,计算同比增长率,排名变化率等

【知识点】
  1. rank()over() 跳过相同几个排名
  2. inner join 灵活使用表联结查询
  3. with [table] as (...) 创建一个临时使用的表,不创建的话,可以用表联结或者子查询
  4. cast(x  as type) 转换x的数据类型

【易错点】
  1. 注意排名用rank()over(),跳过相同的几个的排名
  2. 计算排名变化的时候,有负数,需要转换数据类型
  • 一般默认定义的数据类型为signed(有符号类型),取值返回包含有负数范围,一般正负值的差依然等于无符号类型的范围的上限值
  • 当定义为unsigned(无符号类型)时, 取值范围仅为正数范围,下限值为0;
  • 当设置为unsigned时候,报错BIGINT UNSIGNED value is out of range….,所以需要转换成signed



【代码】
with t1 as (select tag,
count(score) as 2021_exam_cnt,
rank() over(order by count(score) desc) as 2021_dranking
from exam_record er1
join examination_info ei1 using(exam_id)
where year(start_time)=2021 and month(start_time) between 1 and 6
group by tag)

select 
    tag,
    2020_exam_cnt,
    2021_exam_cnt,
    concat(round(((2021_exam_cnt-2020_exam_cnt)/2020_exam_cnt)*100,1),'%')as growth_rate,
    2020_dranking,
    2021_dranking,
    cast(t1.2021_dranking as signed)-cast(t2.2020_dranking as signed) as rank_delta
from(
select tag,
count(score) as 2020_exam_cnt,
rank() over(order by count(score) desc) as 2020_dranking
from exam_record er2
join examination_info ei2 using(exam_id)
where year(start_time)=2020 and month(start_time) between 1 and 6
group by tag
)t2
join t1 using(tag)
order by growth_rate desc,2021_dranking desc