with play_log_name as( select month(p.fdate) as month, p.user_id, p.song_id, s.song_name from play_log p join song_info s on p.song_id = s.song_id where s.singer_name = '周杰伦' and year(p.fdate) = 2022 ), usr_age_play as( select pln.month, u.age, pln.song_id, pln.song_name from play_log_name pln join user_info u on pln.user_id = u.user_id ), constrained_age_play_count as ( select month, song_id, song_name, count(*) as play_pv from usr_age_play where age between 18 and 25 group by month, song_id, song_name ), ranked_songs as ( select month, song_name, play_pv, row_number() over(partition by month order by play_pv desc, song_id asc ) as ranking from constrained_age_play_count ) select month, ranking, song_name, play_pv from ranked_songs where ranking <=3 order by month, ranking
with t as ( select month(fdate) as `month` ,row_number() over (partition by month(fdate) order by count(*) desc,song_id) as ranking ,song_name ,count(*) as play_pv from play_log join user_info using(user_id) join song_info using(song_id) where year(fdate) = '2022' and age between 18 and 25 and singer_name = '周杰伦' group by month(fdate),song_name,song_id #因为窗口函数中用到song_id排序。所以分组时要加上song_id ) select * from t where ranking <= 3
SELECT * FROM (SELECT MONTH(fdate) month, ROW_NUMBER() OVER(PARTITION BY MONTH(fdate) ORDER BY COUNT(s.song_id) DESC,p.song_id ASC) ranking, song_name,COUNT(s.song_id) play_pv FROM user_info u LEFT JOIN play_log p ON u.user_id=p.user_id LEFT JOIN song_info s ON p.song_id=s.song_id WHERE YEAR(fdate)=2022 AND (age BETWEEN 18 AND 25) AND (singer_name='周杰伦') GROUP BY month,song_name,p.song_id) t1 WHERE ranking IN(1,2,3);如果提交报错,可能是因为存在排名听歌数量相同但是排名不一样的歌曲,因此需要在窗口函数的orderby部分按照song_id再降序排列即可.
select * from ( # 按月份分区、按播放总量降序、歌曲id升序进行rank排序 select a.month, row_number() over(partition by a.month order by play_pv desc, song_id asc) as ranking, song_name, play_pv from ( # 先搜索周杰伦22年每个月的不同歌曲及播放总量 select month(pl.fdate) as month, si.song_name, count(si.song_name) as play_pv, si.song_id from play_log as pl inner join song_info as si on si.song_id = pl.song_id inner join user_info as ui on ui.user_id = pl.user_id where ui.age >= 18 and ui.age <= 25 and year(pl.fdate) = 2022 and si.singer_name = "周杰伦" group by month(pl.fdate), si.song_name, si.song_id ) a ) b having ranking <= 3
select * from ( select month(fdate) as month, row_number() over (partition by month(fdate) order by count(*) desc, play_log.song_id) as ranking, song_name, count(*) as play_pv from play_log left join song_info on play_log.song_id = song_info.song_id left join user_info on play_log.user_id = user_info.user_id where 18 <= age and age <= 25 and year(fdate) = '2022' and singer_name = '周杰伦' group by month(fdate), song_name, play_log.song_id ) as t where ranking <= 3
with t as( select month(pl.fdate) as month, rank() over (partition by month(pl.fdate) order by count(pl.song_id) desc,si.song_id) as ranking, si.song_name as song_name, count(*) as play_pv from play_log pl,song_info si,user_info ui where pl.user_id=ui.user_id and pl.song_id = si.song_id and ui.age between 18 and 25 and si.singer_name = '周杰伦' and year(pl.fdate) ='2022' group by month(pl.fdate),song_name,pl.song_id ) select * from t where ranking <= 3
千幸万苦终于搞懂了
首先链接三张表,按照18-25,2022年,周杰伦的歌筛选条件,用rank函数对同一月份的总播放数排序,rank函数在排序时会有两个排序相等的情况,给他多设置一个参数可以解决这个问题,或者使用ROW_NUMBER()函数
select month, ranking, song_name, play_pv from ( select month(p.fdate) month, ( row_number() over ( partition by month(p.fdate) order by count(s.song_name) desc, p.song_id ) ) ranking, s.song_name, count(s.song_name) play_pv from play_log p left join song_info s on p.song_id = s.song_id left join user_info u on p.user_id = u.user_id where (u.age between 18 and 25) and (year(p.fdate) = 2022) and (s.singer_name = '周杰伦') group by month(p.fdate), s.song_name, p.song_id ) n1 where ranking < 4
SELECT month,ranking,song_name,play_pv FROM( SELECT MONTH(t.fdate) AS month, t1.song_name AS song_name, COUNT(*) AS play_pv, ROW_NUMBER() OVER (PARTITION BY MONTH(t.fdate) ORDER BY COUNT(*) DESC,t1.song_id ASC ) AS ranking FROM play_log AS t INNER JOIN song_info t1 ON t.song_id=t1.song_id INNER JOIN user_info t2 ON t.user_id=t2.user_id WHERE t2.age BETWEEN 18 AND 25 AND year(fdate)=2022 AND t1.singer_name='周杰伦' GROUP BY month,t1.song_name,t1.song_id ) AS temp WHERE temp.ranking<=3 ORDER BY month, ranking
select xx.month, xx.ranking, xx.song_name, xx.play_pv from ( select x.month, row_number() over ( partition by x.month order by x.play_pv desc, x.song_id asc ) as ranking, x.song_name, x.play_pv from ( select month(a.fdate) as month, b.song_name, count(a.song_id) as play_pv, a.song_id from play_log a left join song_info b on a.song_id = b.song_id left join user_info c on a.user_id = c.user_id where b.singer_name = "周杰伦" and c.age >= 18 and c.age <= 25 and year(a.fdate) = 2022 group by month, song_name, song_id ) x ) xx where ranking <= 3
WITH song_pv_month AS ( SELECT MONTH (fdate) AS `month`, song_name, song_id, COUNT(*) AS play_pv FROM play_log LEFT JOIN user_info USING (user_id) LEFT JOIN song_info USING (song_id) WHERE age >= 18 AND AGE <= 25 AND YEAR (fdate) = 2022 AND singer_name = '周杰伦' GROUP BY MONTH (fdate), song_name, song_id ), song_pv_month_rank AS ( SELECT `month`, ROW_NUMBER() OVER ( PARTITION BY `month` ORDER BY play_pv DESC, song_id ) AS `ranking`, song_name, play_pv FROM song_pv_month ) SELECT `month`, ranking, song_name, play_pv FROM song_pv_month_rank WHERE ranking <= 3