HiveSQL:求累计访问量

数据

userIdvisitDatevisitCount
u012017/1/215
u022017/1/236
u032017/1/228
u042017/1/203
u012017/1/236
u012017/2/218
U022017/1/236
U012017/2/224

需求一:逐行求相同用户的累计访问次数

在这里插入图片描述
有两种思路:

1,开窗

关键在于开窗后 rows between ... and的使用

rows between unbounded preceding and current row表示从第一行到当前行

select userId,
visitDate,
sum(visitCount) over(partition by userId order by visitDate asc rows between unbounded preceding and current row )
 from visit;

2,join

这种解法比较巧妙,类似于求成绩Top3的思路。

select 
  tmp1.userId,
  tmp2.visitDate,
  sum(tmp1.visitCount) as visitCount
from visit tmp1
left join  visit tmp2
on tmp1.userId = tmp2.userId
where tmp1.visitDate <= tmp2.visitDate
group by userId,tmp2.visitDate

下面以userId=u01的数据为例,分步骤详细结合代码和图示详细解释

ID日期访问次数
u012017/1/215
u012017/1/236
u012017/2/218

join的效果

先不group by,且看看join的效果是咋样的。
注意join的条件和后面的where条件,特别是要结合后面结果表,体会下where条件的巧妙

select 
 *
from visit tmp1
left join  visit tmp2
on tmp1.userId = tmp2.userId
where tmp1.visitDate <= tmp2.visitDate

JOIN+where过滤后结果如下:

tmp1.IDtmp1.日期tmp1. 访问次数tmp2.IDtmp2.日期tmp2.访问次数
u012017/1/215u012017/1/215
u012017/1/215u012017/1/236
u012017/1/236u012017/1/236
u012017/1/215u012017/2/218
u012017/1/236u012017/2/218
u012017/2/218u012017/2/218

大家仔细观察,如果以tmp2.visitDate分组、对tmp1.visitCount求和会怎样?

结论是:恰好计算出从第一天到当前天的访问次数的总和。

再次强调,理解where条件非常关键。

需求二:按月求相同用户的累计访问次数

其实这个需求和上个需求思路差不多,不过是统计口径有差别,上面是安天,这里是按月,所以要先将日期转换为月份,然后按月group by统计出每个月的总访问量,之后就和上面的需求的思路一致了。

1,日期转换为月,并按月汇总

日期转换为月使用了from_unixtimeunix_timestamp两个函数。

select
	userId,
	from_unixtime(unix_timestamp(visitDate, 'yyyy/MM/dd'), 'yyyy-MM') visitMonth,
	sum(visitCount) vc
from
	visit
group by
	userId,
	from_unixtime(unix_timestamp(visitDate, 'yyyy/MM/dd'), 'yyyy-MM')

2,接下来的处理如第一个需求有两种思路

开窗

with tmp as (
select
	userId,
	from_unixtime(unix_timestamp(visitDate, 'yyyy/MM/dd'), 'yyyy-MM') visitMonth,
	sum(visitCount) vc
from
	visit
group by
	userId,
	from_unixtime(unix_timestamp(visitDate, 'yyyy/MM/dd'), 'yyyy-MM'))
select
	tmp1.userId,
	tmp2.visitMonth,
	sum(tmp1.vc)
from
	tmp tmp1
left join tmp tmp2 on
	tmp1.userId = tmp2.userId
where
	tmp1.visitMonth <= tmp2.visitMonth
group by
	tmp1.userId,
	tmp2.visitMonth;

JOIN

select
	userId,
	visitMonth,
	sum(vc) over(partition by userId
order by
	userId,
	visitMonth rows between unbounded preceding and current row)
from
	(
	select
		userId,
		from_unixtime(unix_timestamp(visitDate, 'yyyy/MM/dd'), 'yyyy-MM') visitMonth,
		sum(visitCount) vc
	from
		visit
	group by
		userId,
		from_unixtime(unix_timestamp(visitDate, 'yyyy/MM/dd'), 'yyyy-MM') )tmp;

开窗和JOIN区别

二者都能得出正确的结果,在计算引擎为MapReduce的情况下,开窗比JOIN要快,从执行计划可以看出缘由,JOIN有多次Shuffle,开窗只有一次。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小手追梦

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

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

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

打赏作者

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

抵扣说明:

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

余额充值