数据仓库 用户留存主题

需求:计算前1天,2天,3天的用户留存数量和用户留存率。

用户留存:某段时间内的新增用户,经过一段时间后,仍然使用应用的被认作是留存用户;这部分用户占当时新增用户的比例即是留存率。例如,5月份新增用户200,这200人在6月份启动过应用的有100人,7月份启动过应用的有80人,8月份启动过应用的有50人;则5月份新增用户一个月后的留存率是50%,二个月后的留存率是40%,三个月后的留存率是25%。

实现思路:例如,要计算2019-02-11的1日留存用户,需要知道两种数据,一是2019-02-10新增了哪些用户(在每日新增设备明细表中),二是2019-02-11的活跃用户有哪些(用每日活用户表中)。如果一个用户既是2019-02-10的新增用户,又是2019-02-11的活跃用户,此用户即为2019-02-10的1日留存用户。

数据来源:DWS层的日活表和新增设备明细表。

DWS层(每日留存用户明细表)

建表语句。

分析:

①此表采用了分区表的形式,以每天的日期为分区。因为每天都有自己的1日留存,2日留存,3日留存。。。等情况,数据量相对较大。但因为都是针对新增设备的留存明细,数据量只能说相对较大,并没有达到非用分区表不可的地步。

②表中有两个重要的字段,设备新增时间和直到今日的留存天数。例如,在2010-02-11那天,数据可能出现设备新增日期为2019-02-10,留存天数为1的数据;设备新增日期为2019-02-09,留存天数为2的数据。。。等等。

③DWS层还只是一个留存明细表,具体有多少留存,还需要取ADS做count操作。

drop table if exists dws_user_retention_day;
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/'

数据导入,以2019-02-11的1日,2日,3日留存为例

分析:

①在sql中,用户活跃日期固定为统计日期(2019-02-11),而设备新增日期随着留存天数retention_day 不同,在统计日期(2019-02-11)上减去相应的天数。

②将所有的sql结果进行union all,就得到了2019-02-11相对于2019-02-10的1日留存,相对于2019-02-09的2日留存和相对于2019-02-08的3日留存。若要计算其他留存天数,进行类似重复操作即可。

insert overwrite table dws_user_retention_day
partition(dt="2019-02-11")
select
    nm.mid_id,
    nm.user_id,
    nm.version_code,
    nm.version_name,
    nm.lang,
    nm.source,
    nm.os,
    nm.area,
    nm.model,
    nm.brand,
    nm.sdk_version,
    nm.gmail,
    nm.height_width,
    nm.app_time,
    nm.network,
    nm.lng,
    nm.lat,
    nm.create_date,
    1 retention_day 
from dws_uv_detail_day ud join dws_new_mid_day nm  on ud.mid_id =nm.mid_id 
where ud.dt='2019-02-11' and nm.create_date=date_add('2019-02-11',-1)

union all
select  
    nm.mid_id,
    nm.user_id , 
    nm.version_code , 
    nm.version_name , 
    nm.lang , 
    nm.source, 
    nm.os, 
    nm.area, 
    nm.model, 
    nm.brand, 
    nm.sdk_version, 
    nm.gmail, 
    nm.height_width,
    nm.app_time,
    nm.network,
    nm.lng,
    nm.lat,
    nm.create_date,
    2 retention_day 
from  dws_uv_detail_day ud join dws_new_mid_day nm   on ud.mid_id =nm.mid_id 
where ud.dt='2019-02-11' and nm.create_date=date_add('2019-02-11',-2)

union all
select  
    nm.mid_id,
    nm.user_id , 
    nm.version_code , 
    nm.version_name , 
    nm.lang , 
    nm.source, 
    nm.os, 
    nm.area, 
    nm.model, 
    nm.brand, 
    nm.sdk_version, 
    nm.gmail, 
    nm.height_width,
    nm.app_time,
    nm.network,
    nm.lng,
    nm.lat,
    nm.create_date,
    3 retention_day 
from  dws_uv_detail_day ud join dws_new_mid_day nm   on ud.mid_id =nm.mid_id 
where ud.dt='2019-02-11' and nm.create_date=date_add('2019-02-11',-3);

ADS层留存用户数和留存用户比率

建表语句

分析:注意,此表既包括留存数量,也包括用户留存比率(某日的n天留存,有2个条件)

drop table if exists ads_user_retention_day_rate;
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/';

导入数据。

①数据来源于上一张用户每日留存明细表。

②where条件dt='2019-02-11',说明要拿出每日留存明细表中2019-02-11的所有数据(不同留存天数)。

②group by create_date,retention_day,分组条件有2个,其实只用一个条件分组也可以,但是select的字段必须是分组字段,或者在聚合函数里,为了方便,用这两个条件分组,且不影响结果。

③留存率 = 留存用户数 / 当天新增用户总数。所以需要 join ADS层的ads_new_mid_count ,里面保存了每日新增的用户(设备)数量。

insert into table ads_user_retention_day_rate
select 
    '2019-02-11', 
    ur.create_date,
    ur.retention_day, 
    ur.retention_count, 
    nc.new_mid_count,
    ur.retention_count/nc.new_mid_count*100
from 
(
    select
        create_date,
        retention_day,
        count(*) retention_count
    from dws_user_retention_day
    where dt='2019-02-11' 
    group by create_date,retention_day
) ur join ads_new_mid_count nc on nc.create_date=ur.create_date;

猜你喜欢

转载自www.cnblogs.com/noyouth/p/13196676.html