题目1:
有十万个淘宝店铺,每个顾客访问任意一个店铺时都会生成一条访问日志。访问日志存储表为visit,其中访问用户ID字段名称为uid,访问的店铺字段名称为store,请统计每个店铺的UV。
select store,count(distinct uid) as uv from visit group by store;
题目2:
有一亿个用户,被存储于表Users中,其中有用户唯一字段UID,用户年龄age和用户总消费金额total,请以代码或技术方案阐述的方式分别用sql(Hive 或 Spark Sql)和Spark按照用户年龄从大到小进行排序,如果年龄相同,则按照总消费金额从小到大排序。
select *
from Users
order by age desc , total;
题目3:
当前有用户人生阶段表LifeStage,有用户唯一ID字段UID,用户人生阶段字段stage_someone,其中stage_someone字段内容为各个人生阶段标签按照英文逗号分隔的拼接内容,如:计划买车,已买房,并且每个用户的内容不同,请使用Hive Sql统计每个人生阶段的用户量。
select
stage_name,count( distinct UID)
from LifeStage
LATERAL VIEW explode(split(stage_someone,',')) LifeStage_tmp as stage_name group by stage_name;
知识点:Hive列转行
explode 函数:处理map结构的字段,将数组转换成多行.
步骤1:建表LifeStage:
--对不同用户的人生阶段使用数组,所以建表时要标明数组的分隔符语句--collection items terminated by ","
create table LifeStage(
UID string,
stage_someone array<string>)
row format delimited
fields terminated by "\t"
collection items terminated by ",";
插入数据(BDP查询平台可以直接txt导入)
load data local inpath "/LifeStage.txt" into table LifeStage;
步骤2:explode的使用
explode作用:处理map结构的字段,将数组转换为多行
select explode(stage_someone) from LifeStage;
如果要得到题目的需求结果,那么需要在此结果上,每一个UID和该用户对应的人生阶段进行笛卡尔积
select UID,explode(stage_someone) from LifeStage;
查询结果直接报错,因为UID的记录数要远少于stage_someone的记录数,
那么,由此引入LATERAL VIEW函数:
LATERAL VIEW:
1、LATERAL VIEW用于和UDTF函数【explode,split】结合来使用。
2、首先通过UDTF函数将数据拆分成多行,再将多行结果组合成一个支持别名的虚拟表。
3、主要解决在select使用UDTF做查询的过程中查询只能包含单个UDTF,不能包含其它字段以及多个UDTF的情况。
4、语法:LATERAL VIEW udtf(expression) table Alias AS column Alias(',',columnAlias)
使用LATERAL VIEW+explode 函数进行查询,语句如下:
select UID,stage_name
from LifeStage
LATERAL VIEW explode(stage_someone) tmpTable as stage_name;
--stage_name是给explode(stage_someone)列起的别名
explode 与lateral view 在关系型数据库中本身是不该出现得,因为它得出现本身就是在操作不满足第一范式得数据(每个属性都不可再分),本身已经违背了数据库的设计原理(不论是业务系统还是数据仓库系统),不过大数据技术普及后,很多类似pv、uv的数据,在业务系统中是存储在非关系型数据库中,用json存储的概率比较大,直接导入hive为基础的数仓系统中,就需要经过ETL过程解析这类数据,explode和lateral view在这种场景下大显身手。
网友评论