互联网大厂SQL真题(三)

题目:近一个月发布的视频中热度最高的top3视频

4e5d0a31908a453787b75a6be052691d.png

790c2e7bd8484aae844243ffcf5df000.png

问题:找出近一个月发布的视频中热度最高的top3视频。

  • 热度=(a*视频完播率+b*点赞数+c*评论数+d*转发数)*新鲜度;
  • 新鲜度=1/(最近无播放天数+1);
  • 当前配置的参数a,b,c,d分别为100、5、3、2。
  • 最近播放日期以end_time-结束观看时间为准,假设为T,则最近一个月按[T-29, T]闭区间统计。
  • 结果中热度保留为整数,并按热度降序排序。

 adae3272b6e647369b05ac2403ddfda9.png

 

 Solution

本题虽然最终只需要求热度这一个指标,但其中热度是一个计算公式,其涉及到了相当多的指标,所以需要分开来一个一个看。根据热度计算公式和给定的表,不难得出最简单的几个指标就是点赞数,评论数和转发数,这三个指标通过简单group by加聚合函数就可以得出。

现在来关注其它指标,首先是视频完播率,通过观察表和给定输出示例可以发现,video_info里的duration单位应该是秒,因此我们可以使用timediff(second, date1, date2)这个函数来判断一个视频是否完播,如果end_time和start_time的差大于等于对应的duration,那么就代表完播。而因为是求完播率,再加上count(video_id)作为分母就行,实际上也就是这里使用avg()就行。该指标代码如下:

select
    avg(if(timediff(SECOND, start_time, end_time)>=duration, 
    1, 0)) as finish_rate
from
    tb_user_video_log
    left join
    tb_video_info
    on tb_user_video_log.video_id = tb_video_info.video_id

接下来是新鲜度指标,由于新鲜度涉及到了无播放天数,所以我们首先得知道一个视频的最近播放日期是多少,也就是max(date(end_time)),这部分代码如下:

select
    max(date(end_time)) as cur_dt
from
    tb_user_video_log

为了求最近无播放天数,我们需要求video_info里的release_time和cur_dt的天数差,此时我们可以将上述代码封装成一个子表,用left join on 1 = 1的方式将该表与其它表连接,此时就可计算出无播放天数。再补充上其它指标,我们可以得出下述代码:

SELECT
            video_id,
            AVG(
                IF(
                    TIMESTAMPDIFF(SECOND, start_time, end_time) >= duration,
                    1,
                    0
                )
            ) as finish_rate,
            SUM(if_like) as like_cnt,
            COUNT(comment_id) as comment_cnt,
            SUM(if_retweet) as retweet_cnt,
            MAX(DATE(end_time)) as recent_end_dt,
            MAX(DATE(release_time)) as release_dt,
             --由于使用了group by,这里需要避免语法错误所以加max
            MAX(cur_dt) as cur_dt 
        FROM
            tb_user_video_log
            JOIN tb_video_info 
            on tb_user_video_log.video_id = tb_video_info.video_id
            LEFT JOIN (
                SELECT
                    MAX(DATE(end_time)) as cur_dt
                FROM
                    tb_user_video_log
            ) as tb_max_dt ON 1 = 1
        GROUP BY
            video_id
        HAVING
            TIMESTAMPDIFF(DAY, release_dt, cur_dt) <= 29

由于题目限定时间为近一个月,所以在group by之后加了一个having条件用于限定时间。

最后,根据热度计算公式,可以得出最终代码如下:

SELECT
    video_id,
    ROUND(
        (
            100 * finish_rate + 5 * like_cnt + 3 * comment_cnt + 2 * retweet_cnt
        ) / (TIMESTAMPDIFF(DAY, recent_end_dt, cur_dt) + 1),
        0
    ) as hot_index
FROM
    (
        SELECT
            video_id,
            AVG(
                IF(
                    TIMESTAMPDIFF(SECOND, start_time, end_time) >= duration,
                    1,
                    0
                )
            ) as finish_rate,
            SUM(if_like) as like_cnt,
            COUNT(comment_id) as comment_cnt,
            SUM(if_retweet) as retweet_cnt,
            MAX(DATE(end_time)) as recent_end_dt,
            MAX(DATE(release_time)) as release_dt,
            MAX(cur_dt) as cur_dt 
        FROM
            tb_user_video_log
            JOIN tb_video_info 
            on tb_user_video_log.video_id = tb_video_info.video_id
            LEFT JOIN (
                SELECT
                    MAX(DATE(end_time)) as cur_dt
                FROM
                    tb_user_video_log
            ) as tb_max_dt ON 1 = 1
        GROUP BY
            video_id
        HAVING
            TIMESTAMPDIFF(DAY, release_dt, cur_dt) <= 29
    ) as t_video_info
ORDER BY
    hot_index DESC
LIMIT
    3;

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LkChase

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值