视频号数据分析组外包招聘笔试题时间限时 45 分钟完成。
题目 根据 3 张表表结构,写出具体求解的 SQL 代码 (搞笑品类定义:视频分类或者视频创建者分类为“搞笑”)
1、表创建语句:
create table t_user_video_action_d(
ds int,
user_id string,
video_id string,
action_type int,
`timestamp` bigint
)
row format delimited
fields terminated by ',';
create table t_video_d(
ds int ,
video_id string,
video_type string,
video_user_id string,
video_create_time bigint,
video_description string
)
row format delimited
fields terminated by ',';
create table t_video_user_d(
ds int,
video_user_id string,
video_user_name string,
video_user_type string
)
row format delimited
fields terminated by ',';
题目 1:输出一张搞笑品类 dws 表,用于分析作者近 3 条视频情况:输出每个视频 创建者 user_id 最近发布的 3 个视频,在过去一周内的曝光,点赞总数;需要产出字段:视频 创 建者 user_id,曝光用户数,点赞用户数,曝光次数、点赞次
select `current_date`();
select unix_timestamp();
select unix_timestamp()-7*24*3600;
select from_unixtime(1725326963+8*3600);
with t as (
select uva.user_id,action_type,row_number() over (partition by uva.user_id order by video_create_time desc ) px from t_user_video_action_d uva join t_video_d tvd on uva.user_id=tvd.video_user_id
and uva.video_id = tvd.video_id where tvd.video_type='搞笑' and video_create_time >= (unix_timestamp()-7*24*3600)
)
select
user_id,
count(if(t.action_type=1,t.user_id,null) ) `曝光用户数`,
count(if(t.action_type=2,t.user_id,null) ) `点赞用户数`,
count(if(t.action_type=1,1,null) ) `曝光次数`,
count(if(t.action_type=1,1,null) ) `点赞次数`
from t where t.px <= 3 group by user_id;
题目 2:输出一个取数结果:在 20221103 日创建的视频中,如果视频描述中带有 "搞笑段 子”,“脱口秀”两个关键词即为“搞笑类内容”,不带有这两个关键词为“非搞笑类内 容”,最终输出 20221103 日搞笑与非搞笑视频去重数量
-- 假如你创建的是分区表,其实可以使用分区表字段进行判断 ds = '20221103'
select "搞笑类视频" `类别`,count(1) `数量` from t_video_d
where video_description like '%搞笑段子%' or video_description like '%脱口秀%'
and from_unixtime(t_video_d.video_create_time+8*3600,'yyyyMMdd') ='20221103'
union
select "非搞笑类视频",count(1) from t_video_d
where video_description not like '%搞笑段子%' and video_description not like '%脱口秀%'
and from_unixtime(t_video_d.video_create_time+8*3600,'yyyyMMdd') ='20221103';
-- 第二种写法
select
sum(case when video_description like '%搞笑段子%' or video_description like '%脱口秀%' then 1 else 0 end) `搞笑视频数量`,
sum(case when video_description not like '%搞笑段子%' and video_description not like '%脱口秀%' then 1 else 0 end) `非搞笑视频数量`
from t_video_d where from_unixtime(t_video_d.video_create_time+8*3600,'yyyyMMdd') ='20221103';
题目 3:计算每个用户每天第一次曝光视频的时间戳,运行速度越快越好,输出字段 日期, 用户 id,时间戳
-- 一个人一天刷了很多抖音,他刷第一个抖音的时候是几点几分。
select user_id,ds,min(`timestamp`) from
t_user_video_action_d where action_type = 1 group by user_id,ds;
题目 4:输出一张 dws 表,查询过去任意日期的曝光活跃用户的 7 日留存率,输出字 段日 期,用户 id,7 日留存率具体表结构如下表 1 用户行为表:t_user_video_action_d
l分区:ds(格式 yyyyMMdd)
l主键:user_id、video_id
l含义:一个用户对一个视频的所有行为聚合,每天增量 字段名字段含义类型
留存用户:某段时间内的新增用户,经过一段时间后,又继续使用应用的被认作是留存用户。
留存率:留存用户占新增用户的比例即是留存率
比如:7月1日新增用户100,这100人中在7月2日启动过应用的有30人,7月3日启动过应用的有25人,7月4日启动过应用的有32人
可以这样说7月 1的 1日留存用户 有30人,2日留存用户有25人,3日留存用户有32人。
则7月1日新增用户次日的留存率是30/100=30%,两日留存率是25/100=25%,三日留存率是32/100=32%
1日留存,3日留存,7日留存,30日留存等
假如2023-12-05日数据出来后,可以计算12-04的1日留存,12-03的2日留存,12-02的3日留存。留存不需要连续。
假如一个人12-04日是新增用户,他12-05日活跃了,可以这样说 这个人是 12-04日的1日留存用户。
在留存的天数中,是不需要连续的。
方案一:
-- 先查看曝光的用户和日期
with t as (
-- 9-10 zhangsan
-- 9-10 lisi
-- 9-17 zhangsan
select ds,user_id from t_user_video_action_d where action_type = 1 group by user_id,ds
)
-- 让7天前的数据 处于 当前数据 = 留存率 ds=20240910
, t2 as (
select ds,user_id from t where ds =
date_add(from_unixtime(unix_timestamp("20240910",'yyyyMMdd'),'yyyy-MM-dd'),7)
)
select
t.user_id,count(t2.user_id)/count(t.user_id) `七日留存率`
from t left join t2 on t.user_id = t2.user_id group by t.user_id;
-- 如何将20240910 --> 2024-09-10
-- 字符串转时间戳
select unix_timestamp("20240910",'yyyyMMdd');
select from_unixtime(unix_timestamp("20240910",'yyyyMMdd'),'yyyy-MM-dd');
select date_add(to_date('2024-09-10'),7);
-- 拓展 通过拼接的方式将20240910 --> 2024-09-10
SELECT
concat(
substr('20240910', 1, 4),
'-',
lpad(substr('20240910', 5, 2), 2, '0'),
'-',
lpad(substr('20240910', 7, 2), 2, '0')
) as formatted_date;
方案二:
with ActiveUsers as (
select ds,user_id,
row_number() over (partition by user_id order by ds asc) as rn
from t_user_video_action_d
where action_type = 1
),RetainedUsers as (
select a.user_id,
a.ds as active_date,
count(distinct case when ua.ds = a.ds + interval 7 day then ua.user_id else null end) as retained_count
from ActiveUsers a
left join t_user_video_action_d ua on a.user_id = ua.user_id and ua.ds = a.ds + interval 7 day and ua.action_type = 1
group by a.user_id,a.ds
)select r.active_date,
r.user_id,
retained_count / count(distinct active_date) over (partition by active_date) as retention_rate
from RetainedUsers r;