select *
from(
select month,row_number() over(partition by a.month order by a.play_pv desc) as ranking,song_name,play_pv
from(
select month,t.song_name,sum(if(t.song_name is not null,1,0)) over(partition by t.month,t.song_name) as play_pv
from(
select month(fdate) as month,song_name
from song_info
left join play_log
on song_info.song_id=play_log.song_id
left join user_info
on user_info.user_id=play_log.user_id
where year(fdate)=2022 and (age between 18 and 25) and singer_name='周杰伦'
order by song_info.song_id asc) t) a  #这里需要按照歌的id升序一下,不然最终结果有的行是相反的
group by month,song_name) c  #计算播放次数的时候需要按照月和歌名进行分组
where ranking<=3 

1️⃣先把题目中的三个表链接起来,加入题目所给的条件(2022年,18-25岁,周杰伦),筛选出最基础的表t数据——月份及歌名(原始数据,不去重,为下一步计算每首歌的播放次数作准备)。在这一步,需要按照歌的id升序一下,不然最终结果有的行是相反的。

2️⃣在t表的基础上,去计算每首歌的播放次数,这一步需要按照月份和歌名进行分组,不然会出现同个月份同首歌的数据会出现好多行(行数应该是等于它的播放次数)。这样形成a表,把最终结果需要的字段按照最终顺序能写的都写上去。

3️⃣在a表的基础上,按照每首歌的播放次数进行降序排序(用窗口函数,根据月份进行分组)。这样形成c表,这一步也是,把最终结果需要的字段按照最终顺序能写的都写上去。

4️⃣在c表的基础上,根据播放次数的降序排序,添加条件,选择前三的歌。