百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

大厂SQL笔试【某短视频】

toyiye 2024-06-21 12:34 11 浏览 0 评论

源数据

用户-视频互动表tb_user_video_log

id

uid

video_id

start_time

end_time

if_follow

if_like

if_retweet

comment_id

1

101

2001

2021-10-01 10:00:00

2021-10-01 10:00:30

0

1

1

NULL

2

102

2001

2021-10-01 10:00:00

2021-10-01 10:00:24

0

0

1

NULL

3

103

2001

2021-10-01 11:00:00

2021-10-01 11:00:34

0

1

0

1732526

4

101

2002

2021-09-01 10:00:00

2021-9-01 10:00:42

1

0

1

NULL

5

102

2002

2021-10-01 11:00:00

2021-10-01 10:00:30

1

0

1

NULL

(uid-用户ID, video_id-视频ID, start_time-开始观看时间, end_time-结束观看时间, if_follow-是否关注, if_like-是否点赞, if_retweet-是否转发, comment_id-评论ID)

短视频信息表tb_video_info

id

video_id

author

tag

duration

release_time

1

2001

901

影视

30

2021-01-01 07:00:00

2

2002

901

美食

60

2021-01-01 07:00:00

3

2003

902

旅游

90

2021-01-01 07:00:00

(video_id-视频ID, author-创作者ID, tag-类别标签, duration-视频时长(秒), release_time-发布时间)

问题:计算2021年里有播放记录的每个视频的完播率(结果保留三位小数),并按完播率降序排序

视频完播率是指完成播放次数占总播放次数的比例。简单起见,结束观看时间与开始播放时间的差>=视频时长时,视为完成播放。

输出示例

示例数据的结果如下:

video_id

avg_comp_play_rate

2001

0.667

2002

0.000

SQL代码

#方法1使用sum函数
select
    a.video_id,
    round(sum(if(timestampdiff(second, a.start_time, a.end_time) >= b.duration,1,0))/count(a.video_id),3) as  avg_comp_play_rate
from
    tb_user_video_log a
    join tb_video_info b on a.video_id = b.video_id
where
    year (a.start_time)=2021
group by a.video_id
order by avg_comp_play_rate desc

#方法2使用avg函数
select
    a.video_id,
    round(avg(if(timestampdiff(second, a.start_time, a.end_time) >= b.duration,1,0)),3) as  avg_comp_play_rate
from
    tb_user_video_log a
    join tb_video_info b on a.video_id = b.video_id
where
    year (a.start_time)=2021
group by a.video_id
order by avg_comp_play_rate desc

注意区分timestampdiff()与datediff()用法

timestampdiff()函数的作用是返回两个日期时间之间的整数差。而datediff()函数的作用也是返回两个日期值之差。

它们的函数语法分别为:

TIMESTAMPDIFF(unit,start_time,end_time)

DATEDIFF(start_time,end_time)

问题:计算各类视频的平均播放进度,将进度大于60%的类别输出。

注:

  • 播放进度=播放时长÷视频时长*100%,当播放时长大于视频时长时,播放进度均记为100%。
  • 结果保留两位小数,并按播放进度倒序排序。

输出示例

示例数据的输出结果如下:

tag

avg_play_progress

影视

90.00%

美食

75.00%

SQL代码

select tag,concat(avg_1,'%') avg_play_progress
from
(
 select b.tag ,
round(avg(if( timestampdiff(second,a.start_time,a.end_time)>b.duration,1, timestampdiff(second,a.start_time,a.end_time)/b.duration))*100,2) as avg_1

from tb_user_video_log a
join tb_video_info b
on a.video_id=b.video_id

group by b.tag
having avg_1>60
)t
order by avg_play_progress desc

问题:统计在有用户互动的最近一个月(按包含当天在内的近30天算,比如10月31日的近30天为10.2~10.31之间的数据)中,每类视频的转发量和转发率(保留3位小数)。

:转发率=转发量÷播放量。结果按转发率降序排序。

输出示例

示例数据的输出结果如下

tag

retweet_cut

retweet_rate

影视

2

0.667

美食

1

0.500

SQL代码

select b.tag,
sum(a.if_retweet) as retweet_cut,
round(avg(a.if_retweet),3) as retweet_rate
from tb_user_video_log  a
join tb_video_info b on a.video_id=b.video_id
where 
date(a.start_time) >=  date_sub((select max(start_time) from tb_user_video_log ),INTERVAL 30 DAY)
group by b.tag
order by retweet_rate desc

注意:
date(a.start_time) >=  date_sub((select max(start_time) from tb_user_video_log ),INTERVAL 30 DAY)
不能写成
date(a.start_time) >=  date_sub(max(start_time),INTERVAL 30 DAY)
知道原因的同学跟我说一下

注意date_sub函数用法

DATE_SUB() 函数从日期减去指定的时间间隔。
DATE_SUB(date,INTERVAL expr type)

实例:DATE_SUB("2023-3-2",INTERVAL 1 day) 返回的是2023-3-1

问题:计算2021年里每个创作者每月的涨粉率及截止当月的总粉丝量

  • 涨粉率=(加粉量 - 掉粉量) / 播放量。结果按创作者ID、总粉丝量升序排序。
  • if_follow-是否关注为1表示用户观看视频中关注了视频创作者,为0表示此次互动前后关注状态未发生变化,为2表示本次观看过程中取消了关注。

解题思路:

  • 联结
  • 按照作者和月进行分组:group by author,date_format(start_time,"%Y-%m")
  • 涨粉率:加粉和减粉变化(粉丝变化):sum(if(if_follow=2,-1,if_follow))播放量:count(1)
  • 截止当月的总粉丝量sum(粉丝变化)over(partition by author order by date_format(start_time,"%Y-%m"))
  • 条件:2021年
方法1:
select a.author,
date_format(b.start_time,'%Y-%m') as month,
round(sum(if(b.if_follow=2,-1,b.if_follow))/count(1),3) as fans_growth_rate,
sum(sum(if(b.if_follow=2,-1,b.if_follow))) over(partition by a.author order by date_format(b.start_time,'%Y-%m')) as total_fans
from  tb_video_info a
join  tb_user_video_log b on a.video_id=b.video_id
WHERE YEAR(b.start_time)=2021
group by a.author,month
order by a.author,total_fans

方法2:
with
    main as(
        #统计每个用户的播放量、加粉量、掉粉量
        select
            author,
            mid(start_time,1,7) as month,
            count(start_time) as b,
            count(if(if_follow = 1, 1, null)) as follow_add,
            count(if(if_follow = 2, 1, null)) as follow_sub
        from tb_user_video_log a, tb_video_info b
        where a.video_id = b.video_id
        and year(start_time) = 2021
        group by author,month
    )
#计算2021年里每个创作者每月的涨粉率及截止当月的总粉丝量
select
    author,
    month,
    round((follow_add-follow_sub)/b ,3) as fans_growth_rate,
    sum(follow_add-follow_sub) over(partition by author order by month) as total_fans
from main
order by author,total_fans

关于开窗函数用法可以参考学习:https://blog.csdn.net/weixin_43997319/article/details/124964670

问题:统计2021年国庆头3天每类视频每天的近一周总点赞量和一周内最大单天转发量,结果按视频类别降序、日期升序排序。假设数据库中数据足够多,至少每个类别下国庆头3天及之前一周的每天都有播放记录。

输出示例

示例数据的输出结果如下

tag

dt

sum_like_cnt_7d

max_retweet_cnt_7d

旅游

2021-10-01

5

2

旅游

2021-10-02

5

3

旅游

2021-10-03

6

3

解释:

由表tb_user_video_log里的数据可得只有旅游类视频的播放,2021年9月25到10月3日每天的点赞量和转发量如下:

tag

dt

like_cnt

retweet_cnt

旅游

2021-09-25

1

2

旅游

2021-09-26

0

1

旅游

2021-09-27

1

0

旅游

2021-09-28

0

1

旅游

2021-09-29

0

1

旅游

2021-09-30

1

1

旅游

2021-10-01

2

1

旅游

2021-10-02

1

3

旅游

2021-10-03

1

0

因此国庆头3天(10.01~10.03)里10.01的近7天(9.25~10.01)总点赞量为5次,单天最大转发量为2次(9月25那天最大);同理可得10.02和10.03的两个指标。

SQL代码

with t as 
(select b.tag,
mid(a.start_time,1,10) as dt,
sum(sum(a.if_like)) over (partition by b.tag order by mid(a.start_time,1,10) rows 6 preceding) as sum_like_cnt_7d,
max(sum(a.if_retweet)) over (partition by b.tag order by mid(a.start_time,1,10) rows 6 preceding) as max_retweet_cnt_7d

from tb_user_video_log a
join tb_video_info b on a.video_id=b.video_id
where datediff('2021-10-03',mid(a.start_time,1,10))<9
group by b.tag,dt
)
select * from t 
where dt >='2021-10-01' and dt<='2021-10-03'
order by tag desc,dt asc

开窗函数

  • rows n perceding:从当前行到前n行(一共n+1行)
  • rang/rows between 边界规则1 and 边界规则2:rang表示按照值的范围进行定义框架,rows表示按照行的范围进行定义框架

①rows between 2 perceding and 2 following #当前行往前2行+当前行+当前行往后2行(一共5行)

②rows between 1 following 3 following #当前行的后1——>后3(共3行)

③rows between unbounded preceding and current row #从第一行到当前行

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

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

输出示例

示例数据的输出结果如下

video_id

hot_index

2001

122

2002

56

2003

1

解释:

最近播放日期为2021-10-03,记作当天日期;近一个月(2021-09-04及之后)发布的视频有2001、2002、2003、2004,不过2004暂时还没有播放记录;

视频2001完播率1.0(被播放次数4次,完成播放4次),被点赞3次,评论1次,转发2次,最近无播放天数为0,因此热度为:(100*1.0+5*3+3*1+2*2)/(0+1)=122

同理,视频2003完播率0,被点赞数1,评论和转发均为0,最近无播放天数为3,因此热度为:(100*0+5*1+3*0+2*0)/(3+1)=1(1.2保留为整数)。

SQL代码

with t1 as
(select a.video_id,
avg(if(timestampdiff(second,a.start_time,a.end_time)>=b.duration,1,0)) as a,  #视频完播率
sum(a.if_like) as b,  #点赞数
count(a.comment_id)  as c,  #评论数
sum(a.if_retweet) as d,  #转发数
datediff((select max(end_time) from tb_user_video_log),max(a.end_time)) as f  #最近无播放天数
from tb_user_video_log a
join tb_video_info b on a.video_id=b.video_id
where date(b.release_time) > date_sub((select max(end_time) from tb_user_video_log),interval 30 day)
group by a.video_id
)

select video_id,
round((a*100+b*5+c*3+d*2)/(f+1),0) as hot_index
from t1
order by hot_index desc
limit 3

题目本身不复杂,但是理解题目好难 … 比如,最近无播放天数,一直理解成最近两次播放天数间的间隔天数,实际要简单很多,就是整体最近的播放日期减每个视频的最近播放日期。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码