做流量数据分析的小伙伴经常会遇到流量数据多维度汇总的问题,比如运营希望看到分城市,业务线,用户类型,频道,一级类目和二级类目等维度的交叉数据,因为整体UV并不等于各维度UV的加和,所有整体UV需要单独计算,最后将计算结果和分维度的计算结果union起来,这样代码会特别长,举一个简单例子:
用户日志表为analyst.user_lot,device_id为设备ID,pingdao为各频道名称,计算整体和各频道的PV和UV代码如下:
select
date as event_date
,'all' as pingdao
,count(distinct device_id) as uv
,count(device_id) as pv
from analyst.user_log
where date='20200529'
group by date,'all'
union all
select
date as event_date
,pingao
,count(distinct device_id) as uv
,count(device_id) as pv
from analyst.user_log
where date='20200529'
group by date,pingao
运行结果:(这里为了简化,假设只有三个频道搜索,banner和商家推荐)
event_date | pingao | uv | pv |
---|---|---|---|
20200529 | all | 500 | 6000 |
20200529 | 搜索 | 300 | 3000 |
20200529 | banner | 200 | 2000 |
20200529 | 商家推荐 | 100 | 1000 |
如果我们要维度特别多的话,我们的代码会特别长(例如有3个维度,每个维度又2个值,我们需要union all六段代码,才能看到所有维度的汇总和明细数据),hive提供了一个grouping_id set() 函数来解决以上问题,例如以上问题代码可以简化为:
select
date as event_date
,pingdao
,Grouping_ID as group_id
,count(distinct device_id) as uv
,count(device_id) as pv
from analyst.user_log
where date='20200529'
group by date,pingdao
group by sets(date,(date,pingdao))
运行结果:(这里为了简化,假设只有三个频道:搜索,banner和商家推荐)
event_date | pingao | group_id | uv | pv |
---|---|---|---|---|
20200529 | /N | 1 | 500 | 6000 |
20200529 | 搜索 | 0 | 300 | 3000 |
20200529 | banner | 0 | 200 | 2000 |
20200529 | 商家推荐 | 0 | 100 | 1000 |
按照group by后面的变量排列顺序,grouping sets()的组合中出现的变量赋值0,未出现的变量赋值1,这样会生成一个二进制数字,最后将二进制数字转化成十进制后的数字赋值给group_id变量,例如上面代码运行逻辑:
(date,null)二进制数值:01 → 十进制数字为1
(date,pingdao) 二进制数值:00 →十进制数字为0