日期 用户 年龄
11,test_1,2311,test_2,1911,test_3,3911,test_1,2311,test_3,3911,test_1,2312,test_2,1913,test_1,231、-- 所有用户的总数及平均年龄selectcount(*) sum_user,avg(age) avg_age
from(select
user_id,avg(age) age
from test_five_active
groupby user_id
) t1;-- 活跃人数的总数及平均年龄select-- (5)最外一层算出活跃用户的个数以及平均年龄count(*),avg(d.age)from(select--(4) 最后还需要以user_id分组,去重(防止某个用户在11,12号连续活跃,然后在14,15号又连续活跃,导致diff求出不一致,所以此用户会出现两次)
c.user_id,
c.age
from(select--(3) 以用户和差值diff分组,看分组下的数据的个数是否大于等于2(连续两天登录),取出活跃用户的数据
b.user_id,
b.age,
b.diff,count(*) flag
from(select--(2)用活跃日期减去排名,求出差值,看差值是否相等,相等差值的数据肯定是连续活跃的数据
a.active_time,
a.user_id,
a.age,
a.rank_time,
a.active_time-a.rank_time diff
from(select--(1)以用户和活跃日期分组(去重,防止某个用户在同一天活跃多次),求出每个用户的活跃日期排名
active_time,
user_id,
age,
rank()over(partitionby user_id orderby active_time) rank_time
from test_five_active
groupby active_time,user_id,age
) a
) b
groupby b.user_id,b.age,b.diff
havingcount(*)>=2) c
groupby c.user_id,c.age
) d;
三、TOPN
3.1、每个店铺访问次数top3的访客信息。输出店铺名称、访客id、访问次数
有50W个京东店铺,每个顾客访客访问任何一个店铺的任何一个商品时都会产生一条访问日志,
访问日志存储的表名为Visit,访客的用户id为user_id,被访问的店铺名称为shop,数据如下:
u1 a
u2 b
u1 b
u1 a
u3 c
u4 b
u1 a
u2 c
u5 b
u4 b
u6 c
u2 c
u1 b
u2 a
u2 a
u3 a
u5 a
u5 a
u5 a
step1:统计每个用户对于某一个店铺的访问总次数
step2:利用窗口函数按照店铺分区,访问次数降序排序
step3:取出排名小于等于3SELECT t2.shop,
t2.user_id,
t2.cnt
FROM(SELECT t1.*,
rank()over(partitionBY t1.shop
ORDERBY t1.cnt DESC) rank
FROM(SELECT user_id,
shop,count(*)AS cnt
FROM test_sql.test2
GROUPBY user_id,
shop) t1)t2
WHERE rank <=3;
3.2 编写sql语句实现每班前三名,分数一样并列,同时求出前三名按名次排序的一次的分差
数据集
119019021901903190183419016051902666190223719029981902679190287createtableifnotexists stu(
stu_no string,
class string,
score int)row format delimited fieldsterminatedby' 'linesterminatedby'\n'
stored as textfile
;
step1:调用开窗函数按照班级进行分区,按照分数进行降序排序。
step2:利用lag()函数计算前一名的分数,计算差值
select
class,
stu_no,
score,
num,
score-nvl(lag(score)over(distribute by class sort by num),0)from(select
stu_no,
class,
score,
rank()over(distribute by class sort by score desc) num
from stu) t1
where t1.num<4;
注:NVL(exp1,exp2) 如果expr1为NULL,返回值为 expr2,否则返回expr1。
LAG(col,n,DEFAULT) 用于统计窗口内往上第n行值.第一个参数为列名,第二个参数为往上第n行(可选,默认为1),第三个参数为默认值(当往上第n行为NULL时候,取默认值,如不指定,则为NULL)
数据源
order_id order_type order_time
111 N 10:00111 A 10:05111 B 10:10
是用hql获取结果如下:
order_id order_type_1 order_type_2 order_time_1 order_time_2
111 N A 10:0010:05111 A B 10:0510:10select*from(select order_id
,order_type as type1
,lead(order_type)over(partitionby order_id orderby order_time)as type2
,order_time as time1
,lead(order_time)over(partitionby order_id orderby order_time)as time2
from order_type
)as t1
where t1.type2 isnotnull
六、其他
6.1 计算除去部门最高工资,和最低工资的平均工资
step1:使用rank(),按照部分分区,分别按照工资进行升序,降序排序
step2:将step1作为临时表,分别取出排名第一个高的最高工资,和排名第一低的最低工资
step3:按照部门聚合,求取平均工资
select a.deptno,avg(a.salary)from(select*,rank()over(partitionby deptno orderby salary )as rank_1
,rank()over(partitionby deptno orderby salary desc)as rank_2
from emp
) a
where a.rank_1 >1and a.rank_2 >1groupby a.deptno
6.2 、某天每个直播间最大在线人数或者什么时候直播间人数达到峰值
一张表有如下字段:
1)直播间: live_id
2)用户:userid
3)时间戳:date_stamp
4)登陆类型:entry_type (登入和登出)
求直播间在某一天同一时间点的最大在线用户数?
step1:根据用户的进入和出去使用casewhen 进行类型判断,进入为1,出去为-1
step2:使用sum开窗,按照直播间进行分区,按照时间升序排序,某一时刻直播间的人数。
step3:使用row_number(),按照直播间进行分区,在线人数进行降序拍序,取第一个
select live_id
,date_stamp
,sumflag
from(select live_id
,userid
,date_stamp
,sumflag
,row_number()over(partiotion by live_id orderby sumflag desc) rn
from(select live_id
,userid
,date_stamp
,sum(flag)over(partiotion by live_id orderby date_stamp) sumflag
from(select live_id
, userid
, date_stamp as date_stamp
,casewhen entry_type ='enter'then1when entry_type ='out'then-1else0endas flag
from live_tab lt1
)a
) b
) c
where rn=1;