基于Apache的电商数据仓库(五)

欢迎

你好!这是我历经1个半月的学习(Apache和CDH),做完的一个项目,本次和你们分享一下Apache版。
感谢您的阅读!

第1章~第4章在基于Apache的电商数据仓库(一)
第5章~第5章在基于Apache的电商数据仓库(二)
第6章~第8章在基于Apache的电商数据仓库(三)
第8章~第9章在基于Apache的电商数据仓库(四)
第10章~第12章在基于Apache的电商数据仓库(五)
第13章~第13章在基于Apache的电商数据仓库(六)
第14章~第14章在基于Apache的电商数据仓库(七)

第10章 DWS层搭建

10.1 用户活跃主题

  • 10.1.1 每日活跃设备明细
  1. 建表
create external table dws_uv_detail_day
(
    `mid_id` string COMMENT '设备唯一标识',
    `user_id` string COMMENT '用户标识', 
    `version_code` string COMMENT '程序版本号', 
    `version_name` string COMMENT '程序版本名', 
    `lang` string COMMENT '系统语言', 
    `source` string COMMENT '渠道号', 
    `os` string COMMENT '安卓系统版本', 
    `area` string COMMENT '区域', 
    `model` string COMMENT '手机型号', 
    `brand` string COMMENT '手机品牌', 
    `sdk_version` string COMMENT 'sdkVersion', 
    `gmail` string COMMENT 'gmail', 
    `height_width` string COMMENT '屏幕宽高',
    `app_time` string COMMENT '客户端日志产生时的时间',
    `network` string COMMENT '网络模式',
    `lng` string COMMENT '经度',
    `lat` string COMMENT '纬度'
)
partitioned by(dt string)
stored as parquet
location '/warehouse/gmall/dws/dws_uv_detail_day';
  1. 分析

需求

一、 活跃用户:
① 用户: 每个设备作为一个用户!mid号是用户的相关标识!
②活跃: 打开了应用,称为活跃用户!只要打开了应用,此时会产生启动日志信息!
二、每日活跃设备明细:求每天的活跃设备明细,因此表应该是一个按照日期分区的分区表
明细: 需要把cm字段的所有数据都写入到此表中

相关表
从dwd_start_log启动日志表中取数据

思路
从dwd_start_log中查询数据时,需要根据mid号进行去重,将同一个设备产生的多条明细信息去重后再拼接,一个设备在表中以一行存在

  1. sql
insert overwrite table gmall.dws_uv_detail_day PARTITION(dt='2021-02-08')
SELECT 
mid_id, 
concat_ws('|',collect_set(user_id)) user_id,
concat_ws('|',collect_set(version_code)) version_code,
concat_ws('|',collect_set(version_name)) version_name, 
concat_ws('|',collect_set(lang)) lang, 
concat_ws('|',collect_set(source)) source,
concat_ws('|',collect_set(os)) os, 
concat_ws('|',collect_set(area)) area, 
concat_ws('|',collect_set(model)) model,
concat_ws('|',collect_set(brand)) brand,
concat_ws('|',collect_set(sdk_version)) sdk_version,
concat_ws('|',collect_set(gmail)) gmail,
concat_ws('|',collect_set(height_width)) height_width,
concat_ws('|',collect_set(app_time)) app_time,
concat_ws('|',collect_set(network)) network,
concat_ws('|',collect_set(lng)) lng, 
concat_ws('|',collect_set(lat)) lat
FROM gmall.dwd_start_log
where dt='2021-02-08'
group by mid_id
  • 10.1.2 每周活跃设备明细
  1. 建表
create external table dws_uv_detail_wk( 
    `mid_id` string COMMENT '设备唯一标识',
    `user_id` string COMMENT '用户标识', 
    `version_code` string COMMENT '程序版本号', 
    `version_name` string COMMENT '程序版本名', 
    `lang` string COMMENT '系统语言', 
    `source` string COMMENT '渠道号', 
    `os` string COMMENT '安卓系统版本', 
    `area` string COMMENT '区域', 
    `model` string COMMENT '手机型号', 
    `brand` string COMMENT '手机品牌', 
    `sdk_version` string COMMENT 'sdkVersion', 
    `gmail` string COMMENT 'gmail', 
    `height_width` string COMMENT '屏幕宽高',
    `app_time` string COMMENT '客户端日志产生时的时间',
    `network` string COMMENT '网络模式',
    `lng` string COMMENT '经度',
    `lat` string COMMENT '纬度',
    `monday_date` string COMMENT '周一日期',
    `sunday_date` string COMMENT  '周日日期' 
) COMMENT '活跃用户按周明细'
PARTITIONED BY (`wk_dt` string)
stored as parquet
location '/warehouse/gmall/dws/dws_uv_detail_wk/';
  1. 分析

需求
周活跃: 在一周中,只要启动一次APP,就算是周活跃用户

相关表
从dws_uv_detail_day表中取数据

思路
一、选取一周的范围,作为过滤的条件;
二、从dws_uv_detail_day中查询数据时,需要根据mid号进行去重,将同一个设备产生的多条明细信息去重后再拼接,一个设备在表中以一行存在;
三、求导入数据当前日期所在的周一和周日
①周一: date_sub(next_day(‘2021-02-08’,‘mo’),7)
date_add(next_day(‘2021-02-08’’,‘mo’),-7)
②周日: date_sub(next_day(‘2021-02-08’’,‘mo’),1)
错误:
date_sub(next_day(‘2021-02-08’’,‘sunday’),7)
因为国外周日为第一天,所以这么查询是上周的周日,不是这周的周日 wk_dt(分区列):
concat(date_sub(next_day(‘2021-02-08’’,‘mo’),7),’-’,date_sub(next_day(‘2021-02-08’’,‘mo’),1))

  1. sql
insert overwrite table dws_uv_detail_wk partition(wk_dt)
select  
    mid_id,
    concat_ws('|', collect_set(user_id)) user_id,
    concat_ws('|', collect_set(version_code)) version_code,
    concat_ws('|', collect_set(version_name)) version_name,
    concat_ws('|', collect_set(lang)) lang,
    concat_ws('|', collect_set(source)) source,
    concat_ws('|', collect_set(os)) os,
    concat_ws('|', collect_set(area)) area, 
    concat_ws('|', collect_set(model)) model,
    concat_ws('|', collect_set(brand)) brand,
    concat_ws('|', collect_set(sdk_version)) sdk_version,
    concat_ws('|', collect_set(gmail)) gmail,
    concat_ws('|', collect_set(height_width)) height_width,
    concat_ws('|', collect_set(app_time)) app_time,
    concat_ws('|', collect_set(network)) network,
    concat_ws('|', collect_set(lng)) lng,
    concat_ws('|', collect_set(lat)) lat,
    date_add(next_day('2021-02-08','MO'),-7),
    date_add(next_day('2021-02-08','MO'),-1),
    concat(date_add( next_day('2021-02-08','MO'),-7), '_' , date_add(next_day('2021-02-08','MO'),-1) 
)
from dws_uv_detail_day 
where dt>=date_add(next_day('2021-02-08','MO'),-7) and dt<=date_add(next_day('2021-02-08','MO'),-1) 
group by mid_id;
  • 10.1.3 每月活跃设备明细
  1. 建表
create external table dws_uv_detail_mn( 
    `mid_id` string COMMENT '设备唯一标识',
    `user_id` string COMMENT '用户标识', 
    `version_code` string COMMENT '程序版本号', 
    `version_name` string COMMENT '程序版本名', 
    `lang` string COMMENT '系统语言', 
    `source` string COMMENT '渠道号', 
    `os` string COMMENT '安卓系统版本', 
    `area` string COMMENT '区域', 
    `model` string COMMENT '手机型号', 
    `brand` string COMMENT '手机品牌', 
    `sdk_version` string COMMENT 'sdkVersion', 
    `gmail` string COMMENT 'gmail', 
    `height_width` string COMMENT '屏幕宽高',
    `app_time` string COMMENT '客户端日志产生时的时间',
    `network` string COMMENT '网络模式',
    `lng` string COMMENT '经度',
    `lat` string COMMENT '纬度'
) COMMENT '活跃用户按月明细'
PARTITIONED BY (`mn` string)
stored as parquet
location '/warehouse/gmall/dws/dws_uv_detail_mn/';
  1. 分析

相关表
从dws_uv_detail_day表中取数据

思路
一、选取一月的范围,作为过滤的条件;
二、从dws_uv_detail_day中查询数据时,需要根据mid号进行去重,将同一个设备产生的多条明细信息去重后再拼接,一个设备在表中以一行存在;

  1. sql
insert overwrite table dws_uv_detail_mn partition(mn)
select  
    mid_id,
    concat_ws('|', collect_set(user_id)) user_id,
    concat_ws('|', collect_set(version_code)) version_code,
    concat_ws('|', collect_set(version_name)) version_name,
    concat_ws('|', collect_set(lang)) lang,
    concat_ws('|', collect_set(source)) source,
    concat_ws('|', collect_set(os)) os,
    concat_ws('|', collect_set(area)) area, 
    concat_ws('|', collect_set(model)) model,
    concat_ws('|', collect_set(brand)) brand,
    concat_ws('|', collect_set(sdk_version)) sdk_version,
    concat_ws('|', collect_set(gmail)) gmail,
    concat_ws('|', collect_set(height_width)) height_width,
    concat_ws('|', collect_set(app_time)) app_time,
    concat_ws('|', collect_set(network)) network,
    concat_ws('|', collect_set(lng)) lng,
    concat_ws('|', collect_set(lat)) lat,
    date_format('2021-02-08','yyyy-MM')
from dws_uv_detail_day
where date_format(dt,'yyyy-MM') = date_format('2021-02-08','yyyy-MM')
group by mid_id;
  • 10.1.4 生成脚本

之前讲过公共脚本,这里不讲了

10.2 用户新增主题

  • 10.2.1 每日新增设备明细
  1. 建表
create external table dws_new_mid_day
(
    `mid_id` string COMMENT '设备唯一标识',
    `user_id` string COMMENT '用户标识', 
    `version_code` string COMMENT '程序版本号', 
    `version_name` string COMMENT '程序版本名', 
    `lang` string COMMENT '系统语言', 
    `source` string COMMENT '渠道号', 
    `os` string COMMENT '安卓系统版本', 
    `area` string COMMENT '区域', 
    `model` string COMMENT '手机型号', 
    `brand` string COMMENT '手机品牌', 
    `sdk_version` string COMMENT 'sdkVersion', 
    `gmail` string COMMENT 'gmail', 
    `height_width` string COMMENT '屏幕宽高',
    `app_time` string COMMENT '客户端日志产生时的时间',
    `network` string COMMENT '网络模式',
    `lng` string COMMENT '经度',
    `lat` string COMMENT '纬度',
    `create_date`  string  comment '创建时间' 
)  COMMENT '每日新增设备信息'
stored as parquet
location '/warehouse/gmall/dws/dws_new_mid_day/';
  1. 分析

相关表
dws_uv_detail_day(日活表)中查询
dws_new_mid_day(每日新增设备表)

思路
一、dws_uv_detail_day包含今天所有的活跃用户的信息;所有的活跃用户= 今天的新增用户 + 之前的历史用户 ;
二、要向dws_new_mid_day插入的是2021-02-08的新用户,dws_new_mid_day里面已经有了从应用统计-2021-02-07所有的老用户信息;
三、今天的活跃用户-之前的历史用户=今天的新增用户!

  1. sql
insert into table gmall.dws_new_mid_day
SELECT 
    t1.*
FROM  
(select * from dws_uv_detail_day where dt='2021-02-08') t1
LEFT JOIN gmall.dws_new_mid_day nm
on t1.mid_id=nm.mid_id
WHERE nm.mid_id is null;
  1. 生成脚本

10.3 用户留存主题

  • 10.3.1 每日留存用户明细表
  1. 建表
create external table dws_user_retention_day 
(
    `mid_id` string COMMENT '设备唯一标识',
    `user_id` string COMMENT '用户标识', 
    `version_code` string COMMENT '程序版本号', 
    `version_name` string COMMENT '程序版本名', 
    `lang` string COMMENT '系统语言', 
    `source` string COMMENT '渠道号', 
    `os` string COMMENT '安卓系统版本', 
    `area` string COMMENT '区域', 
    `model` string COMMENT '手机型号', 
    `brand` string COMMENT '手机品牌', 
    `sdk_version` string COMMENT 'sdkVersion', 
    `gmail` string COMMENT 'gmail', 
    `height_width` string COMMENT '屏幕宽高',
    `app_time` string COMMENT '客户端日志产生时的时间',
    `network` string COMMENT '网络模式',
    `lng` string COMMENT '经度',
    `lat` string COMMENT '纬度',
   `create_date`    string  comment '设备新增时间',
   `retention_day`  int comment '截止当前日期留存天数'
)  COMMENT '每日用户留存情况'
PARTITIONED BY (`dt` string)
stored as parquet
location '/warehouse/gmall/dws/dws_user_retention_day/';
  1. 分析

相关表
dws_new_mid_day:每日的新增用户表
dws_uv_detail_day:日活表

思路
一、明细信息:从dws_uv_detail_day(日活表)取
二、create_date: 设备的新增日期(哪一天称为新用户的);从dws_new_mid_day根据mid_id查询;
三、retention_day: 截至到当前日期留存的天数
四、dt(日活数据的日期)=create_date+retention_day

  1. sql
insert overwrite TABLE dws_user_retention_day PARTITION(dt='2021-02-08')
SELECT 
t1.mid_id,
t1.user_id, 
t1.version_code,
t1.version_name, 
t1.lang, 
t1.source,
t1.os,
t1.area,
t1.model,
t1.brand,
t1.sdk_version, 
t1.gmail, 
t1.height_width,
t1.app_time, 
t1.network, 
t1.lng, 
t1.lat,
t2.create_date, 
1 retention_day, 
'2021-02-08'
FROM 
(SELECT * from  gmall.dws_uv_detail_day where dt='2021-02-08') t1
JOIN 
(select mid_id,create_date from  gmall.dws_new_mid_day where create_date=date_sub('2021-02-08',1)) t2
on t1.mid_id=t2.mid_id
  • 10.3.2 求1,2,3,n天的留存明细
  1. sql

> 使用union all链接多个sql

insert overwrite TABLE dws_user_retention_day PARTITION(dt='2021-02-08')
SELECT 
t1.mid_id,
t1.user_id, 
t1.version_code,
t1.version_name, 
t1.lang, 
t1.source,
t1.os,
t1.area,
t1.model,
t1.brand,
t1.sdk_version, 
t1.gmail, 
t1.height_width,
t1.app_time, 
t1.network, 
t1.lng, 
t1.lat,
t2.create_date, 
1 retention_day
FROM 
(SELECT * from  gmall.dws_uv_detail_day where dt='2021-02-08') t1
JOIN 
(select mid_id,create_date from  gmall.dws_new_mid_day where create_date=date_sub('2021-02-08',1)) t2
on t1.mid_id=t2.mid_id
UNION all
SELECT 
t1.mid_id,
t1.user_id, 
t1.version_code,
t1.version_name, 
t1.lang, 
t1.source,
t1.os,
t1.area,
t1.model,
t1.brand,
t1.sdk_version, 
t1.gmail, 
t1.height_width,
t1.app_time, 
t1.network, 
t1.lng, 
t1.lat,
t2.create_date, 
2 retention_day
FROM 
(SELECT * from  gmall.dws_uv_detail_day where dt='2021-02-08') t1
JOIN 
(select mid_id,create_date from  gmall.dws_new_mid_day where create_date=date_sub('2021-02-08',2)) t2
on t1.mid_id=t2.mid_id
UNION all
SELECT 
t1.mid_id,
t1.user_id, 
t1.version_code,
t1.version_name, 
t1.lang, 
t1.source,
t1.os,
t1.area,
t1.model,
t1.brand,
t1.sdk_version, 
t1.gmail, 
t1.height_width,
t1.app_time, 
t1.network, 
t1.lng, 
t1.lat,
t2.create_date, 
3 retention_day
FROM 
(SELECT * from  gmall.dws_uv_detail_day where dt='2021-02-08') t1
JOIN 
(select mid_id,create_date from  gmall.dws_new_mid_day where create_date=date_sub('2021-02-08',3)) t2
on t1.mid_id=t2.mid_id
  • 10.3.3 生成脚本

10.4 每个用户累计访问次数

  1. 建表
create external table dws_user_total_count_day( 
    `mid_id` string COMMENT '设备id',
`subtotal` bigint COMMENT '每日登录小计'
)
partitioned by(`dt` string)
row format delimited fields terminated by '\t'
location '/warehouse/gmall/dws/dws_user_total_count_day';
  1. 分析

需求
向dws_user_total_count_day插入数据

相关表
dwd_start_log(启动日志表)

思路
一、用户每打开一次应用,就会产生一条启动日志;
二、从启动日志表查询,根据用户(mid_id)分组,求每个用户产生的;
三、启动日志的总的数量(count)。

  1. sql
insert overwrite table dws_user_total_count_day PARTITION(dt='2021-02-08')
SELECT 
    mid_id,
    count(*) subtotal
FROM dwd_start_log
where dt='2021-02-08'
GROUP by mid_id;
  1. 生成脚本

10.5 新收藏用户数

  1. 建表
CREATE EXTERNAL TABLE dws_user_action_wide_log(
    `mid_id` string COMMENT '设备id',
    `goodsid` string COMMENT '商品id',
    `display_count` string COMMENT '点击次数',
    `praise_count` string COMMENT '点赞次数',
    `favorite_count` string COMMENT '收藏次数')
PARTITIONED BY (`dt` string)
stored as parquet
location '/warehouse/gmall/dws/dws_user_action_wide_log/'
TBLPROPERTIES('parquet.compression'='lzo');
  1. 分析

相关表
dwd_display_log(商品点击表):mid_id(用户),goodsid(商品id)
dwd_favorites_log(收藏表):mid_id(用户),course_id(商品id)
dwd_praise_log(点赞表): mid_id(用户),target_id(商品id)

思路
一、将用户对每个商品的点击次数,点赞次数,收藏次数等信息汇总到一张宽表中!
二、从以上三个表中,先以用户和商品为单位,进行聚合!
三、从以上三个表中取数据,根据mid_id和商品进行关联!将三个表的信息汇总合并!
合并: 常用join,使用join进行连接操作!
在hive中尽量少用join!
这次可以使用union all

  1. sql
insert overwrite TABLE dws_user_action_wide_log PARTITION(dt='2021-02-08')
select 
    mid_id, 
    goodsid,
    sum(display_count),
    sum(praise_count), 
    sum(favorite_count)
from
(select 
    mid_id,goodsid,count(*) display_count,0 praise_count, 0 favorite_count 
from dwd_display_log
where dt='2021-02-08'
group by mid_id,goodsid
union all
SELECT
    mid_id,target_id goodsid,0 display_count ,count(*) praise_count,0 favorite_count 
from dwd_praise_log
where dt='2021-02-08'
group by mid_id,target_id
union all
select 
    mid_id,course_id goodsid, 0 display_count,0 praise_count, count(*) favorite_count
from dwd_favorites_log
where dt='2021-02-08'
group by mid_id,course_id) tmp
GROUP by mid_id,goodsid
  1. 生成脚本

第11章 ADS层搭建

11.1 用户活跃主题

  • 11.1.1 生成每日,周,月后跃设备数量
  1. 建表
create external table ads_uv_count( 
    `dt` string COMMENT '统计日期',
    `day_count` bigint COMMENT '当日用户数量',
    `wk_count`  bigint COMMENT '当周用户数量',
    `mn_count`  bigint COMMENT '当月用户数量',
    `is_weekend` string COMMENT 'Y,N是否是周末,用于得到本周最终结果',
    `is_monthend` string COMMENT 'Y,N是否是月末,用于得到本月最终结果' 
) COMMENT '活跃设备数'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_uv_count/';
  1. 分析

相关表
dws_uv_detail_day
dws_uv_detail_wk
dws_uv_detail_mn

思路
一、dws_uv_detail_day,使用count(mid_id) 统计 日活跃设备数
二、dws_uv_detail_wk,使用count(mid_id) 统计 周活跃设备数
三、dws_uv_detail_mn,使用count(mid_id) 统计 月活跃设备数
四、is_weekend: 是否是一周的最后一天 if( date_sub(next_day(‘2021-02-08’,‘mo’),1)=‘2021-02-08’,‘Y’,‘N’)
先求当前日期所在的周日: date_sub(next_day(‘2021-02-08’,‘mo’),1)
判断当前日期是否等于当前所在周的周日
五、is_monthend:是否是一月的最后一天 if(last_day(‘2021-02-08’)=‘2021-02-08’,‘Y’,‘N’)

  1. sql
INSERT into table gmall.ads_uv_count
select  
  '2021-02-08' dt,
   daycount.ct,
   wkcount.ct,
   mncount.ct,
   if(date_add(next_day('2021-02-08','MO'),-1)='2021-02-08','Y','N') ,
   if(last_day('2021-02-08')='2021-02-08','Y','N') 
from 
(
   select  
      '2021-02-08' dt,
       count(*) ct
   from dws_uv_detail_day
   where dt='2021-02-08'  
)daycount join 
( 
   select  
     '2021-02-08' dt,
     count (*) ct
   from dws_uv_detail_wk
   where wk_dt=concat(date_add(next_day('2021-02-08','MO'),-7),'_' ,date_add(next_day('2021-02-08','MO'),-1) )
) wkcount on daycount.dt=wkcount.dt
join 
( 
   select  
     '2021-02-08' dt,
     count (*) ct
   from dws_uv_detail_mn
   where mn=date_format('2021-02-08','yyyy-MM')  
)mncount on daycount.dt=mncount.dt;
  1. 生成脚本

11.2 用户新增主题

  • 11.2.1 统计每日新增设备数
  1. 建表
create external table ads_new_mid_count
(
    `create_date`     string comment '创建时间' ,
    `new_mid_count`   BIGINT comment '新增设备数量' 
)  COMMENT '每日新增设备信息数量'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_new_mid_count/';
  1. 分析

相关表
从dws_new_mid_day,执行count统计即可

  1. sql
insert into table ads_new_mid_count 
select
create_date,
count(*)
from dws_new_mid_day
where create_date='2021-02-08'
group by create_date;
  1. 生成脚本

11.3 用户留存主题

  • 11.3.1 每日留存用户的数量
  1. 建表
create external table ads_user_retention_day_count 
(
   `create_date`       string  comment '设备新增日期',
   `retention_day`     int comment '截止当前日期留存天数',
   `retention_count`    bigint comment  '留存数量'
)  COMMENT '每日用户留存情况'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_user_retention_day_count/';
  1. 分析

相关表
dws_user_retention_day

思路
create_date: 从dws_user_retention_day查询
retention_day: 从dws_user_retention_day查询
retention_count: 使用count()统计
先根据create_date过滤指定的新增日期日期用户的设备明细!
再根据retention_day分组,之后count(
)

  1. sql
insert into table gmall.ads_user_retention_day_count
SELECT 
    '2021-02-08', 
    retention_day, 
    count(*)
FROM gmall.dws_user_retention_day
where create_date='2021-02-08'
group by retention_day;
  1. 生成脚本
  • 11.3.2 留存用户比率
  1. 建表
create external table ads_user_retention_day_rate 
(
     `stat_date`          string comment '统计日期',
     `create_date`       string  comment '设备新增日期',
     `retention_day`     int comment '截止当前日期留存天数',
     `retention_count`    bigint comment  '留存数量',
     `new_mid_count`     bigint comment '当日设备新增数量',
     `retention_ratio`   decimal(10,2) comment '留存率'
)  COMMENT '每日用户留存情况'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_user_retention_day_rate/';
  1. 分析

相关表
ads_user_retention_day_count
ads_new_mid_count
从以上两表取出同一条新增的设备的信息,因此设备的新增日期是关联的字段

思路
stat_date : 一般是当前要统计数据的当天或后一天。不早于统计数据的日期!
create_date : 从ads_user_retention_day_count取
retention_day : 从ads_user_retention_day_count取
retention_count : 从ads_user_retention_day_count取
new_mid_count : 从ads_new_mid_count统计当前新增设备的数量
retention_ratio : retention_count/new_mid_count

  1. sql
insert into table ads_user_retention_day_rate
SELECT 
'2021-02-08',
ur.create_date,
ur.retention_day, 
ur.retention_count, 
nm.new_mid_count, 
cast (ur.retention_count / nm.new_mid_count as decimal(10,2))
FROM 
ads_user_retention_day_count ur 
JOIN
ads_new_mid_count nm
on ur.create_date=nm.create_date
where date_add(ur.create_date,ur.retention_day)='2021-02-08'
  1. 生成脚本

11.4 沉默用户数

  1. 建表
create external table ads_silent_count( 
    `dt` string COMMENT '统计日期',
    `silent_count` bigint COMMENT '沉默设备数'
) 
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_silent_count';
  1. 分析

需求

沉默用户:只在安装当天启动过,且启动时间是在一周前;
只在安装当天启动过: 沉默用户只会产生的一天的启动日志;
启动时间是在一周前: 沉默用户产生启动日志的时间,必须距离当前的统计时间已经,间隔了7天.

相关表
日活表dws_uv_detail_day(提前针对mid_id进行了合并)
一个mid_id在日活表中一天最多有1条记录

思路
从日活表中取出统计日期之前的所有数据,按照mid_id(用户设备号)分组,统计日活表所有的记录数=1的mid_id;
再判断,记录数=1的mid_id,当天产生的dt是否已经举例当前间隔了7天.

  1. sql
insert into table ads_silent_count
select 
    '2021-02-24',
    count(*)
from
(select  
    mid_id
from dws_uv_detail_day
where dt<='2021-02-24'
GROUP by mid_id
HAVING COUNT(mid_id)=1 and min(dt)<date_sub('2021-02-24',7)) tmp
  1. 生成脚本

11.5 本周回流用户数

  1. 建表
create external table ads_back_count( 
    `dt` string COMMENT '统计日期',
    `wk_dt` string COMMENT '统计日期所在周',
    `wastage_count` bigint COMMENT '回流设备数'
) 
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_back_count';
  1. 分析

需求
本周回流用户:上周没有使用应用,上周之前使用了应用,本周使用了应用;
本周回流用户=本周日活-本周新增用户-上周日活用户.

相关表
dws_uv_detail_wk: 周活表
dws_new_mid_day: 每日新增用户表

思路
三个结果集做差:
a left join b on a.x=b.x where b.x is null
with
临时表名 as (),
临时表名 as (),
临时表名 as ()
select 语句

  1. sql
with t1 as 
(SELECT 
    mid_id
FROM dws_uv_detail_wk
where wk_dt=concat(date_sub(next_day('2021-02-24','mo'),7),'-',date_sub(next_day('2021-02-24','mo'),1))),
t2 as
(SELECT
    mid_id
from dws_new_mid_day
where create_date BETWEEN date_sub(next_day('2021-02-24','mo'),7) and  '2021-02-24'),
t3 as
(SELECT 
    mid_id
FROM dws_uv_detail_wk
where wk_dt=concat(date_sub(next_day('2021-02-24','mo'),14),'-',date_sub(next_day('2021-02-24','mo'),8)))
insert into table ads_back_count
select 
    '2021-02-24',
    concat(date_sub(next_day('2021-02-24','mo'),7),'-',date_sub(next_day('2021-02-24','mo'),1)),
    count(*)
from
t1 left join t2 on t1.mid_id=t2.mid_id 
left join t3 on t1.mid_id=t3.mid_id
where t2.mid_id is null and t3.mid_id is null
  1. 生成脚本

11.6 连续活跃主题

  • 11.6.1 近连续三周活跃用户数
  1. 建表
create external table ads_continuity_wk_count( 
    `dt` string COMMENT '统计日期,一般用结束周周日日期,如果每天计算一次,可用当天日期',
    `wk_dt` string COMMENT '持续时间',
    `continuity_count` bigint
) 
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_continuity_wk_count';
  1. 分析

需求
连续三周后跃用户: 在当前日期之前三周的周活表中,此用户都存在!
周活表特点按照mid_id进行了去重!
因此如果用户,在连续三周的周活中出现,那么就会有3条对应的记录!

相关表
周活表:dws_dv_detail_wk

思路
求当前日期,之前三周的数据。根据mid分组,分组后统计组内记录数量=3,即是连续三周登录的用户

  • sql
insert into table ads_continuity_wk_count
select 
    '2021-02-24',
    concat(date_sub(next_day('2021-02-24','mo'),21),'_',date_sub(next_day('2021-02-24','mo'),1)),
    count(*)
from    
(select 
    mid_id
from dws_uv_detail_wk
where monday_date BETWEEN date_sub(next_day('2021-02-24','mo'),21)
and '2021-02-24'
  1. 生成脚本
  • 11.6.2 近七天内连续三天活跃用户数
  1. 建表
create external table ads_continuity_uv_count( 
    `dt` string COMMENT '统计日期',
    `wk_dt` string COMMENT '最近7天日期',
    `continuity_count` bigint
) COMMENT '连续活跃设备数'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_continuity_uv_count';
  1. 分析

相关表
日活表: dws_uv_detail_day

思路
取当前日志之前7天的数据;
按照用户mid_id分组,按照日期进行升序排序;
使用rownumber函数,创建一个连续递增的列;
将日期列和rw列,进行做差;
将用户和差值进行分组,组内至少有3条记录,将复合条件的mid_id进行过滤即可;

  1. sql
insert into TABLE ads_continuity_uv_count
select 
    '2021-02-24',
    concat(date_sub('2021-02-24',7),'-','2021-02-24'),
    count(DISTINCT mid_id)
from
(select 
    mid_id
from
(SELECT 
    mid_id,dt,ROW_NUMBER() over(PARTITION by mid_id order by dt  )rn,
    date_sub(dt,ROW_NUMBER() over(PARTITION by mid_id order by dt  )) diff
from dws_uv_detail_day
where dt BETWEEN date_sub('2021-02-24',7) and '2021-02-24') tmp
GROUP by mid_id,diff
having count(*)>=3 ) tmp2
  1. 生成脚本

11.7 各个商品点击次数top3的用户

  1. 建表
create external table ads_goods_count( 
    `dt` string COMMENT '统计日期',
    `goodsid` string COMMENT '商品',
    `user_id` string COMMENT '用户',
    `goodsid_user_count` bigint COMMENT '商品用户点击次数'
) 
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_goods_count';
  1. 分析

相关表
dws_user_action_wide_log

思路
过滤出点击次数>0的用户,取这些用户今天之前的所有数据;
按照商品id和用户id进行分组,统计每个用户对每件商品的累计点击次数;
针对每个商品的每个用户的点击次数,以商品为单位分区,按照用户的点击次数降序排序,求出排名前三的用户!

  1. sql
insert into table ads_goods_count
select 
   '2021-02-24', goodsid,mid_id,totalCount
from 
(select  goodsid,mid_id,totalCount,
RANK() over(PARTITION by goodsid order by totalCount desc )rn
from 
(SELECT
   goodsid,mid_id,sum(display_count) totalCount
from dws_user_action_wide_log
where dt<='2021-02-24' and display_count>0
GROUP by goodsid,mid_id) t1) t2
where rn<=3
  1. 生成脚本

11.8 总点击次数最多的10个用户点击的各个的商品次数

  1. 建表
create external table ads_goods_user_count( 
`dt` string COMMENT '统计日期',
`mid_id` string COMMENT '用户id',
    `u_ct` string COMMENT '用户总点击次数',
    `goodsid` string COMMENT '商品id',
    `d_ct` string COMMENT '各个商品点击次数'
) 
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_goods_user_count';
  1. 分析

相关表
dws_user_action_wide_log

思路
求总点击次数最多的10个用户
再求出此10个用户各自点击的每个商品次数

  1. sql
insert into TABLE ads_goods_user_count
select
  '2021-02-24',
  mid_id,
  u_ct,
  goodsid,
  d_ct
from(
  select
    mid_id,
    u_ct,
    goodsid,
    d_ct,
    row_number() over(partition by mid_id order by d_ct desc ) rn
  from(
    select
      dl.mid_id,
      u_ct,
      dl.goodsid,
      count(*) d_ct
    from dwd_display_log dl join (
      select
        mid_id,
        count(*) u_ct
      from dws_user_action_wide_log
      group by mid_id
      order by u_ct desc
      limit 10
    )t1
    on dl.mid_id=t1.mid_id
    group by dl.mid_id, u_ct, dl.goodsid
  ) t2
) t3
where rn<=10
  1. 生成脚本

11.9 月活跃率

  1. 建表
create external table ads_mn_ratio_count( 
   `dt` string COMMENT '统计日期',
   `mn` string COMMENT '统计月活跃率的月份',
   `ratio` string COMMENT '活跃率'
) 
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_mn_ratio_count';
  1. 分析

需求
月活跃用户与截止到该月累计的用户总和之间的比例

相关表
ads_uv_count: 取月活跃用户
ads_new_mid_count: 取截至到该月所有的用户数

  1. sql
insert into table ads_mn_ratio_count
select
    '2021-02-24',
    date_format('2021-02-24','yyyy-MM'),
    mn_count/sum_user*100 mn_percent
from
(select count(*) mn_count from dws_uv_detail_mn where mn=date_format('2021-02-24','yyyy-MM')) t1,
(select sum(new_mid_count) sum_user from ads_new_mid_count) t2;
  1. 生成脚本

11.10 每个用户累计访问次数

  1. 建表
drop table if exists ads_user_total_count;
create external table ads_user_total_count( 
    `mid_id` string COMMENT '设备id',
    `subtotal` bigint COMMENT '每日登录小计',
    `total` bigint COMMENT '登录次数总计'
)
partitioned by(`dt` string)
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_user_total_count';
  1. 分析

相关表
dws_user_total_count_day

思路
从dws_user_total_count_day中取出每个用户每天登录的次数,
再取出每个用户之前每天登录的次数的总和

  1. sql
insert overwrite table ads_user_total_count PARTITION(dt='2021-02-24')
SELECT
    t1.mid_id,
    t1.subtotal,
    t2.total
from 
(select mid_id,subtotal
from dws_user_total_count_day
where dt='2021-02-24') t1
JOIN
(select mid_id,sum(subtotal) total
FROM dws_user_total_count_day
where dt<='2021-02-24'
GROUP by mid_id) t2
on t1.mid_id=t2.mid_id
  1. 生成脚本

第12章 用户行为数仓部分报错总结

  1. org.apache.tez.dag.api.SessionNotRunning: TezSession has already shutdown

运行Tez时检查到用过多内存而被NodeManager杀死进程问题

关掉虚拟内存检查,修改yarn-site.xml

<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>

第13章 系统业务数仓概念

请移步至基于Apache的电商数据仓库(六)

猜你喜欢

转载自blog.csdn.net/qq_43494678/article/details/115016769