用户画像 用户访问模型表

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zimiao552147572/article/details/88427426

===============  用户访问模型表 ===============

用户上网轨迹表 
        SQL目的:以同一个用户ID作为同一个分组的情况下,同时可根据session_id和cookie_id的不同,计算出该同一用户当天的访问次数和每次访问的停留时长
        1.用户上网轨迹表 BDM层(PC端/网页端)
                用户上网轨迹表 BDM层 bdm.itcast_bdm_user_pc_click_log(时间分区)
                用户上网轨迹表 FDM层 fdm.itcast_fdm_user_pc_pageview(时间分区)
                
        2.用户上网轨迹表 BDM层(APP端)
                用户上网轨迹表 BDM层 bdm.itcast_bdm_user_app_click_log(时间分区)
                用户上网轨迹表 FDM层 fdm.itcast_fdm_user_app_pageview(时间分区)

--------------------------------------------

近30天 PC端/网页端 访问最常用的指标(临时表)
        SQL目的:在同一个用户ID分组下,可对应多个不同 ip/cookie/浏览器名/系统名    的分组的情况下,统计出近30天之内的使用次数情况
        统计近30天之内指标的方式:where dt >= date_add(昨天日期时间, -29)
        没有时间分区,但是每次都会先 drop 临时表,再 CREATE 临时表 as select ...

        近30天 PC端 访问最常用的指标 GDM层 gdm.itcast_gdm_user_visit_temp_01(临时表)
        近30天 PC端 访问最常用的指标 GDM层 = 用户上网轨迹表 FDM层(时间分区)
--------------------------------------------        

用户访问模型表 GDM层
        用户访问模型表 GDM层 gdm.itcast_gdm_user_visit(时间分区)
        用户访问模型表 GDM层 = 客户基本属性表 FDM层(时间分区)
                     + 用户上网轨迹表(PC端/网页端) FDM层(无需时间分区,因为进行了时间日期比较)
                     + 近30天 PC端 访问最常用的指标 GDM层(临时表)
                     + 用户上网轨迹表(APP端) FDM层(无需时间分区,因为进行了时间日期比较)

====================== 用户上网轨迹表 =====================

用户上网轨迹表 
        SQL目的:以同一个用户ID作为同一个分组的情况下,同时可根据session_id和cookie_id的不同,计算出该同一用户当天的访问次数和每次访问的停留时长
        1.用户上网轨迹表 BDM层(PC端/网页端)
                用户上网轨迹表 BDM层 bdm.itcast_bdm_user_pc_click_log(时间分区)
                用户上网轨迹表 FDM层 fdm.itcast_fdm_user_pc_pageview(时间分区)
                
        2.用户上网轨迹表 BDM层(APP端)
                用户上网轨迹表 BDM层 bdm.itcast_bdm_user_app_click_log(时间分区)
                用户上网轨迹表 FDM层 fdm.itcast_fdm_user_app_pageview(时间分区)

--------------------------------------------

用户上网轨迹表BDM层-- PC端/网页端 BDM 层(源数据层)
    create database if not exists bdm;

    create external table if not exists bdm.itcast_bdm_user_pc_click_log(
      session_id STRING,  --sessionID
      cookie_id STRING,   --cookieID
      visit_time STRING,  --请求访问的 日期时间点
      user_id STRING,     --请求访问的 用户ID
      visit_url STRING,   --请求访问的 URL
      visit_os STRING,    --请求访问的 操作系统
      browser_name STRING,--请求访问的 浏览器名称
      visit_ip STRING,    --请求访问的 ip
      province STRING,    --请求访问的 省份
      city STRING,        --请求访问的 城市
      page_id STRING,     --请求访问的 页面ID
      goods_id STRING,    --请求访问的 商品ID
      shop_id STRING      --请求访问的 商店ID
    ) partitioned by (dt string)
    row format delimited fields terminated by ','
    lines terminated by '\n'
    location '/business/itcast_bdm_user_pc_click_log';

    //添加分区
    alter table bdm.itcast_bdm_user_pc_click_log add partition (dt='2017-01-01') location '/business/itcast_bdm_user_pc_click_log/dt=2017-01-01';

    //把BDM层源数据文件导入到 BDM层 外部分区表中
    hdfs dfs -put /root/source_data/itcast_bdm_user_pc_click_log.txt /business/itcast_bdm_user_pc_click_log/dt=2017-01-01

--------------------------------------------

用户上网轨迹表FDM层-- PC端/网页端 FDM 层(对 BDM 源数据层的数据进行清洗和预处理)
    1.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。
      Cookie保存在客户端浏览器中,而Session保存在服务器上。
    2.Cookie的内容主要包括:名字,值,过期时间,路径和域。路径与域一起构成cookie的作用范围。 
        1)Name 和 Value 属性由程序设定,默认值都是空引用。 
        2)Domain属性的默认值为当前URL的域名部分,不管发出这个cookie的页面在哪个目录下的。 
        3)Path属性的默认值是根目录,即 ”/” ,不管发出这个cookie的页面在哪个目录下的。可以由程序设置为一定的路径来进一步限制此cookie的作用范围。 
        4)Expires 属性,这个属性设置此Cookie 的过期日期和时间。
    3.SessionId保存在Cookie中,用户提交了表单时,浏览器会将用户的SessionId自动附加在HTTP头信息中。
    4.Session的生命周期:
        1.超时销毁:客户端不与服务器进行交互后,Session等到自动销毁的时间间隔便会自动销毁
        2.关闭浏览器/重新打开浏览器(Session销毁):之前Cookie中存放的Sessionid就自动销毁了
        3.关闭浏览器/重新打开浏览器(Session定时销毁):
            可以在登录的时候,手动把JSESSIONID保存到COOKIE中,并令其存在的生命周期更长(可以和session的生命周期保持一致),
            这样即使浏览器关闭,cookie也不会消失,JSESSIONID还在,重新打开浏览器后,服务器仍可再找到该session

    create database if not exists fdm;
    create  table if not exists fdm.itcast_fdm_user_pc_pageview(
      session_id STRING,  --sessionID
      cookie_id STRING,   --cookieID
      user_id STRING,     --用户ID
      in_time STRING,     --访问进入时间
      out_time STRING,    --访问离开时间
      stay_time STRING,   --访问停留时间(访问离开时间 减 访问进入时间)
      pv BIGINT,          --PV(访问网站页面的次数)
      visit_os STRING,    --操作系统
      browser_name STRING,--游览器名称
      visit_ip STRING,    --访问ip
      province STRING,    --省份
      city STRING         --城市
    ) partitioned BY (dt STRING);

  SQL目的:
    GROUP BY user_id + session_id + cookie_id 的作用:
        以同一个用户ID作为同一个分组的情况下,同时可根据session_id和cookie_id的不同,计算出该同一用户当天的访问次数和每次访问的停留时长
    GROUP BY session_id 的作用:
        当打开浏览器时自动创建Session,当关闭浏览器时自动销毁(超时销毁)Session,那么即可计算出每次用户在网站中停留的时长。
        当为新Session时,即作为新的网站中停留时长。同一个Session的创建时间作为访问进入时间,同一个Session的自动销毁(超时销毁)的时间作为访问离开时间。
    ----加载数据---
    INSERT overwrite TABLE fdm.itcast_fdm_user_pc_pageview PARTITION (dt = '2017-01-01') 
    SELECT 
      t.session_id,
      t.cookie_id,
      t.user_id,
      //同一个Session的创建时间作为访问进入时间,同一个Session的自动销毁(超时销毁)的时间作为访问离开时间
      MIN(visit_time) in_time, //把最小的请求访问的日期时间点作为访问进入时间
      MAX(visit_time) out_time,//把最大的请求访问的日期时间点作为访问离开时间
      (
        case
          WHEN MIN(visit_time) = MAX(visit_time) //如果访问进入时间等于访问离开时间的话,则设置默认5秒的访问停留时间,比如用户进入网站页面之后不点击任何页面则无法统计用户的访问停留时间
          then 5 
          else unix_timestamp(MAX(visit_time)) - unix_timestamp(MIN(visit_time)) //访问离开时间 减 访问进入时间 得出 访问停留时间
        end
      ) stay_time,
      COUNT(1) pv, //计算出该同一用户当天的访问次数和每次访问的停留时长,获取对应user_id/cookie_id/visit_ip的总PV数
      t.visit_os,
      t.browser_name,
      t.visit_ip,
      t.province,
      t.city 
    FROM
      bdm.itcast_bdm_user_pc_click_log t 
    WHERE dt = '2017-01-01' 
    GROUP BY t.session_id, 
      t.cookie_id,
      t.user_id,
      t.visit_os,
      t.browser_name,
      t.visit_ip,
      t.province,
      t.city ;

--------------------------------------------

用户上网轨迹表BDM层--APP端  BDM 层(源数据层)
    create database if not exists bdm;
    create external table if not exists bdm.itcast_bdm_user_app_click_log(
      user_id string,        --用户ID
      log_time string,       --访问时间
      phone_id string,       --手机ID,唯一标识一台设备
      visit_os string,       --操作系统 android、ios、wp
      os_version string,     --操作系统的版本
      app_name string,       --APP的名称
      app_version string,    --APP的版本
      device_token string,   --PUSH码,消息推送的
      visit_ip string,       --访问ip
      province string,       --省份
      city string            --城市
    ) partitioned by (dt string)
    row format delimited fields terminated by ','
    lines terminated by '\n'
    location '/business/itcast_bdm_user_app_click_log';

    //添加分区
    alter table bdm.itcast_bdm_user_app_click_log add partition (dt='2017-01-01') location '/business/itcast_bdm_user_app_click_log/dt=2017-01-01';

    //把BDM层源数据文件导入到 BDM层 外部分区表中
    hdfs dfs -put /root/source_data/itcast_bdm_user_app_click_log.txt /business/itcast_bdm_user_app_click_log/dt=2017-01-01

    device_token string PUSH码,消息推送用 
        Push指运营人员通过自己的产品或第三方工具对用户移动设备进行的主动消息推送。
        用户可以在移动设备锁定屏幕和通知栏看到push消息通知,通知栏点击可唤起APP并去往相应页面。
        我们平时在锁屏上看到的微信消息等等都属于APP消息推送行列。

--------------------------------------------

用户上网轨迹表FDM层--app端 FDM 层(对 BDM 源数据层的数据进行清洗和预处理)
    create database if not exists fdm;
    create  table if not exists fdm.itcast_fdm_user_app_pageview(
      user_id string,        --用户ID
      log_time string,       --访问时间 2016-12-12 10:20:30
      log_hour string,       --访问具体时间的小时数字:比如早上十点访问,那么小时数字为10,用于后期统计用户什么时间段来访问的
      phone_id string,       --手机ID,唯一标识一台设备
      visit_os string,       --操作系统 android、ios、wp
      os_version string,     --操作系统版本
      app_name string,       --APP的名称
      app_version string,    --APP的版本
      device_token string,   --PUSH码,消息推送的
      visit_ip string,       --访问ip
      province string,       --省份
      city string            --城市
    ) partitioned BY (dt STRING);


    ------加载数据-----
    INSERT overwrite TABLE fdm.itcast_fdm_user_app_pageview PARTITION (dt = '2017-01-01') 
    SELECT 
      t.user_id,
      t.log_time,
      HOUR(t.log_time) log_hour,  //通过 HOUR(具体日期时间) 获取具体日期时间的小时数字
      t.phone_id,
      t.visit_os,
      t.os_version,
      t.app_name,
      t.app_version,
      t.device_token,
      t.visit_ip,
      t.province,
      t.city 
    FROM
      bdm.itcast_bdm_user_app_click_log t 
    WHERE dt = '2017-01-01' ;


================ 近30天 PC端/网页端 访问最常用的指标 ===================

近30天 PC端/网页端 访问最常用的指标(临时表)
        SQL目的:在同一个用户ID分组下,可对应多个不同 ip/cookie/浏览器名/系统名    的分组的情况下,统计出近30天之内的使用次数情况
        统计近30天之内指标的方式:where dt >= date_add(昨天日期时间, -29)
        没有时间分区,但是每次都会先 drop 临时表,再 CREATE 临时表 as select ...

        近30天 PC端 访问最常用的指标 GDM层 gdm.itcast_gdm_user_visit_temp_01(临时表)
        近30天 PC端 访问最常用的指标 GDM层 = 用户上网轨迹表 FDM层(时间分区)
--------------------------------------------        

近30天 PC端/网页端 访问最常用的指标(临时表) BDM 层(源数据层)

    SQL目的:    
        row_number() over(distribute by 用户ID, ip/cookie/浏览器名/系统名 sort by 使用次数 desc) rn 
        在同一个用户ID分组下,可对应多个不同 ip/cookie/浏览器名/系统名    的分组的情况下,统计出近30天之内的使用次数情况
        统计近30天之内指标的方式:where dt >= date_add(昨天日期时间, -29)
    drop table if exists gdm.itcast_gdm_user_visit_temp_01;

    create table gdm.itcast_gdm_user_visit_temp_01 as 
    select 
      t.user_id,
      t.type, // type 为字符串:"visit_ip"、"cookie_id"、"browser_name"浏览器名、"visit_os"系统名
      t.con, // con 分别有 IP地址、cookieID、浏览器名、系统名 的具体内容值
      t.cnt, // cnt 根据type的不同 分别是 IP地址、cookie、浏览器名、系统名 的使用次数
      t.rn 
    from
      (select 
        b.user_id,
        b.con,
        b.type,
        b.cnt,
        row_number() over(distribute by b.user_id, b.type sort by b.cnt desc) rn 
        //排序函数:row_number() over(distribute by(分桶字段名) sort by(排序字段名 ASC/DESC))
        from
        (select 
           a.user_id, a.visit_ip con, 'visit_ip' type, --近30天常用的IP地址
           count(1) cnt //近30天常用的IP地址的总访问记录数
         from
           fdm.itcast_fdm_user_pc_pageview a 
         where dt >= date_add('2017-01-01', -29) //当前时间2017-01-01 减去 29天 统计近30天的数据:用于最终统计每个IP所使用的次数
         group by a.user_id, a.visit_ip 
         union all 
         select 
            a.user_id, a.cookie_id con, 'cookie_id' type, --近30天常用的cookie
            count(1) cnt //近30天常用的cookie的总访问记录数
         from
            fdm.itcast_fdm_user_pc_pageview a 
         where dt >= date_add('2017-01-01', -29)  //当前时间2017-01-01 减去 29天 统计近30天的数据:用于最终统计每个cookie所使用的次数
         group by a.user_id, a.cookie_id 
         union all
         select 
            a.user_id, a.browser_name con, 'browser_name' type, --近30天常用的浏览器
            count(1) cnt //近30天常用的浏览器的总访问记录数
         from
            fdm.itcast_fdm_user_pc_pageview a 
         where dt >= date_add('2017-01-01', -29)  //当前时间2017-01-01 减去 29天 统计近30天的数据:用于最终统计每个浏览器所使用的次数
         group by a.user_id, a.browser_name 
         union all
         select 
            a.user_id, a.visit_os con, 'visit_os' type,  --近30天常用的系统
            count(1) cnt 
         from
            fdm.itcast_fdm_user_pc_pageview a 
         where dt >= date_add('2017-01-01', -29) //当前时间2017-01-01 减去 29天 统计近30天的数据:用于最终统计每个系统所使用的次数
         group by  a.user_id, a.visit_os
               )b
           )t ;


=================== 用户访问模型表 ====================  

用户访问模型表 GDM层
        用户访问模型表 GDM层 gdm.itcast_gdm_user_visit(时间分区)
        用户访问模型表 GDM层 = 客户基本属性表 FDM层(时间分区)
                     + 用户上网轨迹表(PC端/网页端) FDM层(无需时间分区,因为进行了时间日期比较)
                     + 近30天 PC端 访问最常用的指标 GDM层(临时表)
                     + 用户上网轨迹表(APP端) FDM层(无需时间分区,因为进行了时间日期比较)

--------------------------------------------      

生成客户访问模型表
    create database if not exists gdm;
    create  table if not exists gdm.itcast_gdm_user_visit(
    user_id string,              
    latest_pc_visit_date string,            
    latest_app_visit_date string,           
    latest_pc_visit_session string,         
    latest_pc_cookies string,               
    latest_pc_pv string,                    
    latest_pc_browser_name string,          
    latest_pc_visit_os string,              
    latest_app_name string,                 
    latest_app_visit_os string,             
    latest_visit_ip string,                 
    latest_city string,                     
    latest_province string,                 
    first_pc_visit_date string,             
    first_app_visit_date string,            
    first_pc_visit_session string,          
    first_pc_cookies string,                
    first_pc_pv string,                     
    first_pc_browser_name string,           
    first_pc_visit_os string,               
    first_app_name string,                  
    first_app_visit_os string,              
    first_visit_ip string,                  
    first_city string,                      
    first_province string,                  
    day7_app_cnt bigint,                    
    day15_app_cnt bigint,                   
    month1_app_cnt bigint,                  
    month2_app_cnt bigint,                  
    month3_app_cnt bigint,                  
    day7_pc_cnt bigint,                     
    day15_pc_cnt bigint,                    
    month1_pc_cnt bigint,                   
    month2_pc_cnt bigint,                   
    month3_pc_cnt bigint,                   
    month1_pc_days bigint,                  
    month1_pc_pv bigint,                    
    month1_pc_avg_pv bigint,                
    month1_pc_diff_ip_cnt bigint,           
    month1_pc_diff_cookie_cnt bigint,       
    month1_pc_common_ip string,             
    month1_pc_common_cookie string,         
    month1_pc_common_browser_name string,   
    month1_pc_common_os string,             
    month1_hour025_cnt bigint,              
    month1_hour627_cnt bigint,              
    month1_hour829_cnt bigint,              
    month1_hour10212_cnt bigint,            
    month1_hour13214_cnt bigint,            
    month1_hour15217_cnt bigint,            
    month1_hour18219_cnt bigint,            
    month1_hour20221_cnt bigint,            
    month1_hour22223_cnt bigint,            
    dw_date timestamp
    ) partitioned by (dt string);
 
    SQL中:
         1.MAX():此处使用MAX()没有任何业务意义,因为使用了GROUP BY,因此为了语法不报错,所以才使用了MAX()等聚合函数来补全语法
         2.FROM 客户基本属性表 WHERE dt=昨天:后面LEFT JOIN的表都包含近30天/近90天的数据,目的是:仅计算昨天新增用户和访问用户的访问情况
         3.LEFT JOIN 用户上网轨迹表(PC端/网页端)
        1.第一版本:没有使用“where dt >= 前第90天”,而是使用“前第90天 <= in_time <= 昨天”,同样可以统计 近90天之内的表数据
           2.第二版本(推荐):使用“where dt >= 前第90天”,即 where dt >= date_add('2017-01-01', -29),可以达到更加快速地搜索查询表数据
         4.LEFT JOIN 用户上网轨迹表(APP端)
        1.第一版本:没有使用“where dt >= 前第90天”,而是使用“前第90天 <= log_time <= 昨天”,同样可以统计 近90天之内的表数据
           2.第二版本(推荐):使用“where dt >= 前第90天”,即 where dt >= date_add('2017-01-01', -29),可以达到更加快速地搜索查询表数据

    INSERT overwrite TABLE gdm.itcast_gdm_user_visit PARTITION (dt = '2017-01-01') 
    SELECT 
      t.user_id,--客户ID
      MAX(  //此处使用MAX()没有任何业务意义,因为使用了GROUP BY,因此为了语法不报错,所以才使用了MAX()等聚合函数来补全语法
        CASE
          WHEN pc.rn_desc = 1 //当取 pc端的 where rn_desc = 1 时表示取出每个分桶中的第一条数据,代表近90天之内最近一次PC端访问日期
          THEN pc.in_time //返回 近90天之内 最近一次PC端访问日期
        END
      ) latest_pc_visit_date,--近90天之内 最近一次PC端访问日期
      MAX(
        CASE
          WHEN app.rn_desc = 1 //当取 app端的 where rn_desc = 1 时表示取出每个分桶中的第一条数据,代表近90天之内最近一次APP端访问日期
          THEN app.log_time //返回 近90天之内 最近一次APP端访问日期
        END
      ) latest_app_visit_date,--近90天之内 最近一次APP端访问日期
      MAX(
        CASE
          WHEN pc.rn_desc = 1 
          THEN pc.session_id 
        END
      ) latest_pc_visit_session,--近90天之内 最近一次PC端访问的session
      MAX(
        CASE
          WHEN pc.rn_desc = 1 
          THEN pc.cookie_id 
        END
      ) latest_pc_cookies,--近90天之内 最近一次PC端访问的cookies
      MAX(
        CASE
          WHEN pc.rn_desc = 1 
          THEN pc.pv 
        END) latest_pc_pv,--近90天之内 最近一次PC端访问的PV
      MAX(
        CASE
          WHEN pc.rn_desc = 1 
          THEN pc.browser_name 
        END
      ) latest_pc_browser_name,--近90天之内 最近一次PC端访问使用的游览器
      MAX(
        CASE
          WHEN pc.rn_desc = 1 
          THEN pc.visit_os 
        END
      ) latest_pc_visit_os,--近90天之内 最近一次PC端访问使用的操作系统
      MAX(
        CASE
          WHEN app.rn_desc = 1 
          THEN app.app_name 
        END
      ) latest_app_name,--近90天之内 最近一次APP端访问app名称
      MAX(
        CASE
          WHEN app.rn_desc = 1 
          THEN app.visit_os 
        END
      ) latest_app_visit_os,--近90天之内 最近一次APP端访问使用的操作系统
      MAX(
        CASE
          WHEN pc.rn_desc = 1 
          AND app.rn_desc = 1 
          AND pc.in_time >= app.log_time  
          THEN pc.visit_ip
          WHEN pc.rn_desc = 1 
          AND app.rn_desc = 1 
          AND pc.in_time < app.log_time 
          THEN app.visit_ip  
        END
      ) latest_visit_ip,--近90天之内 最近一次访问IP(不分APP与PC)
      MAX(
        CASE
          WHEN pc.rn_desc = 1 //当取 pc端的 where rn_desc = 1 时表示取出每个分桶中的第一条数据,代表离当前最近一次的消费时间
          AND app.rn_desc = 1 //当取 app端的 where rn_desc = 1 时表示取出每个分桶中的第一条数据,代表离当前最近一次的消费时间
          AND pc.in_time >= app.log_time //如果 pc端的 最近的消费时间 大于等于 app端的 最近的消费时间,那么返回 最近一次的pc端消费时间
          THEN pc.city
          WHEN pc.rn_desc = 1 
          AND app.rn_desc = 1 
          AND pc.in_time < app.log_time 
          THEN app.city 
        END
      ) latest_city,--近90天之内 最近一次访问城市(不分APP与PC)
      MAX(
        CASE
          WHEN pc.rn_desc = 1 
          AND app.rn_desc = 1 
          AND pc.in_time >= app.log_time 
          THEN pc.province 
          WHEN pc.rn_desc = 1 
          AND app.rn_desc = 1 
          AND pc.in_time < app.log_time 
          THEN app.province 
        END
      ) latest_province,--近90天之内 最近一次访问省份(不分APP与PC)
      MAX(
        CASE
          WHEN pc.rn_asc = 1 //当取 pc端的 where rn_asc= 1 时表示取出每个分桶中的第一条数据,代表离当前最远的第一次消费时间
          THEN pc.in_time 
        END
      ) first_pc_visit_date,--近90天之内 第一次PC端访问日期
      MAX(
        CASE
          WHEN app.rn_asc = 1 
          THEN app.log_time 
        END
      ) first_app_visit_date,--近90天之内 第一次APP端访问日期
      MAX(
        CASE
          WHEN pc.rn_asc = 1 
          THEN pc.session_id 
        END
      ) first_pc_visit_session,--近90天之内 第一次PC端访问的session
      MAX(
        CASE
          WHEN pc.rn_asc = 1 
          THEN pc.cookie_id 
        END
      ) first_pc_cookies,--近90天之内 第一次PC端访问的cookies
      MAX(
        CASE
          WHEN pc.rn_asc = 1 
          THEN pc.pv 
        END) first_pc_pv,--近90天之内 第一次PC端访问的PV
      MAX(
        CASE
          WHEN pc.rn_asc = 1 
          THEN pc.browser_name 
        END
      ) first_pc_browser_name,--近90天之内 第一次PC端访问使用的游览器
      MAX(
        CASE
          WHEN pc.rn_asc = 1 
          THEN pc.visit_os 
        END
      ) first_pc_visit_os,--近90天之内 第一次PC端访问使用的操作系统
      MAX(
        CASE
          WHEN app.rn_asc = 1 
          THEN app.app_name 
        END
      ) first_app_name,--近90天之内 第一次APP端访问app名称
      MAX(
        CASE
          WHEN app.rn_asc = 1 
          THEN app.visit_os 
        END
      ) first_app_visit_os,--近90天之内 第一次APP端访问使用的操作系统
      MAX(
        CASE
          WHEN pc.rn_asc = 1 //当取 pc端的 where rn_asc= 1 时表示取出每个分桶中的第一条数据,代表离当前最远的第一次消费时间
          AND app.rn_asc = 1 //当取 app端的 where rn_asc= 1 时表示取出每个分桶中的第一条数据,代表离当前最远的第一次消费时间
          AND pc.in_time <= app.log_time //如果 pc端的 最近的消费时间 小于 app端的 最近的消费时间,那么返回 最远的第一次pc端的消费时间
          THEN pc.visit_ip 
          WHEN pc.rn_asc = 1 
          AND app.rn_asc = 1 
          AND pc.in_time > app.log_time 
          THEN app.visit_ip 
        END
      ) first_visit_ip,--近90天之内 第一次访问IP(不分APP与PC)
      MAX(
        CASE
          WHEN pc.rn_asc = 1 
          AND app.rn_asc = 1 
          AND pc.in_time <= app.log_time 
          THEN pc.city 
          WHEN pc.rn_asc = 1 
          AND app.rn_asc = 1 
          AND pc.in_time > app.log_time 
          THEN app.city 
        END
      ) first_city,--近90天之内 第一次访问城市(不分APP与PC)
      MAX(
        CASE
          WHEN pc.rn_asc = 1 
          AND app.rn_asc = 1 
          AND pc.in_time <= app.log_time 
          THEN pc.province 
          WHEN pc.rn_asc = 1 
          AND app.rn_asc = 1 
          AND pc.in_time > app.log_time 
          THEN app.province 
        END
      ) first_province,--近90天之内 第一次访问省份(不分APP与PC)
      SUM(
        CASE
          WHEN app.dat_7 = 1 
          THEN 1 //对每次返回的1都进行sum操作,便可以统计出 近7天APP端访问次数
        END) day7_app_cnt,--近7天APP端访问次数
      SUM(
        CASE
          WHEN app.dat_15 = 1 
          THEN 1 
        END) day15_app_cnt,--近15天APP端访问次数
      SUM(
        CASE
          WHEN app.dat_30 = 1 
          THEN 1 
        END) month1_app_cnt,--近30天APP端访问次数
      SUM(
        CASE
          WHEN app.dat_60 = 1 
          THEN 1 
        END) month2_app_cnt,--近60天APP端访问次数
      SUM(
        CASE
          WHEN app.dat_90 = 1 
          THEN 1 
        END) month3_app_cnt,--近90天APP端访问次数
      COUNT(
        CASE
          WHEN pc.dat_7 = 1 
          THEN pc.session_id 
        END
      ) day7_pc_cnt,--近7天PC端访问次数
      COUNT(
        CASE
          WHEN pc.dat_15 = 1 
          THEN pc.session_id 
        END
      ) day15_pc_cnt,--近15天PC端访问次数
      COUNT(
        CASE
          WHEN pc.dat_30 = 1 
          THEN pc.session_id 
        END
      ) month1_pc_cnt,--近30天PC端访问次数
      COUNT(
        CASE
          WHEN pc.dat_60 = 1 
          THEN pc.session_id 
        END
      ) month2_pc_cnt,--近60天PC端访问次数
      COUNT(
        CASE
          WHEN pc.dat_90 = 1 
          THEN pc.session_id 
        END
      ) month3_pc_cnt,--近90天PC端访问次数
      //substr(pc.in_time,0,10) 截取出 xxxx-xx-xx 的时间日期,然后count对去重后的 时间日期进行统计 访问天数
      COUNT(DISTINCT substr(pc.in_time,0,10)) month1_pc_days,--近30天PC端访问天数
      SUM(
        CASE
          WHEN pc.dat_30 = 1 
          THEN pc.pv 
        END) month1_pc_pv,--近30天PC端访问PV
      SUM(
        CASE
          WHEN pc.dat_30 = 1 
          THEN pc.pv   //近30天PC端访问PV总数除以近30天PC端访问天数得出近30天PC端访问每天平均访问PV
        END) / COUNT(DISTINCT substr(pc.in_time,0,10)) month1_pc_avg_pv,--近30天PC端访问平均PV
      MAX(b.month1_pc_diff_ip_cnt),--近30天PC端访问不同ip数
      MAX(b.month1_pc_diff_cookie_cnt),--近30天PC端访问不同的cookie数
      MAX(b.month1_pc_common_ip),--近30天PC端访问最常用ip
      MAX(b.month1_pc_common_cookie),--近30天PC端访问最常用的cookie
      MAX(b.month1_pc_common_browser_name),--近30天PC端访问最常用游览器
      MAX(b.month1_pc_common_os),--近30天PC端访问最常用的操作系统
      COUNT(
        CASE
          WHEN pc.visit_hour >= 0 //0点
          AND pc.visit_hour <= 5 //5点
          THEN pc.session_id 
        END
      ) month1_hour025_cnt,--近30天PC端0-5点访问次数
      COUNT(
        CASE
          WHEN pc.visit_hour >= 6 
          AND pc.visit_hour <= 7 
          THEN pc.session_id 
        END
      ) month1_hour627_cnt,--近30天PC端6-7点访问次数
      COUNT(
        CASE
          WHEN pc.visit_hour >= 8 
          AND pc.visit_hour <= 9 
          THEN pc.session_id 
        END
      ) month1_hour829_cnt,--近30天PC端8-9点访问次数
      COUNT(
        CASE
          WHEN pc.visit_hour >= 10 
          AND pc.visit_hour <= 12 
          THEN pc.session_id 
        END
      ) month1_hour10212_cnt,--近30天PC端10-12点访问次数
      COUNT(
        CASE
          WHEN pc.visit_hour >= 13 
          AND pc.visit_hour <= 14 
          THEN pc.session_id 
        END
      ) month1_hour13214_cnt,--近30天PC端13-14点访问次数
      COUNT(
        CASE
          WHEN pc.visit_hour >= 15 
          AND pc.visit_hour <= 17 
          THEN pc.session_id 
        END
      ) month1_hour15217_cnt,--近30天PC端15-17点访问次数
      COUNT(
        CASE
          WHEN pc.visit_hour >= 18 
          AND pc.visit_hour <= 19 
          THEN pc.session_id 
        END
      ) month1_hour18219_cnt,--近30天PC端18-19点访问次数
      COUNT(
        CASE
          WHEN pc.visit_hour >= 20 
          AND pc.visit_hour <= 21 
          THEN pc.session_id 
        END
      ) month1_hour20221_cnt,--近30天PC端20-21点访问次数
      COUNT(
        CASE
          WHEN pc.visit_hour >= 22 
          AND pc.visit_hour <= 23 
          THEN pc.session_id 
        END
      ) month1_hour22223_cnt,--近30天PC端22-23点访问次数
      FROM_UNIXTIME(UNIX_TIMESTAMP()) dw_date 
    FROM
      (SELECT user_id 
       FROM fdm.itcast_fdm_user_wide 
       WHERE dt = '2017-01-01' //此处使用“WHERE dt=昨天”,而后面LEFT JOIN的表都包含近30天/近90天的数据,目的是:仅计算昨天新增用户和访问用户的访问情况
            ) t 
    LEFT JOIN 
        (SELECT a.*,
          (
            CASE
              WHEN in_time >= DATE_SUB('2017-01-01', 6) //判断用户访问时间in_time大于等于“当前时间2017-01-01减去6天的”结果值并且小于等于当前时间2017-01-01,那么表示是在近7天之内访问的,便返回1,最终用于统计近7天PC端访问次数
              AND in_time <= '2017-01-01' 
              THEN 1 
            END
          ) dat_7,    --近7天pc端访问次数
          (
            CASE
              WHEN in_time >= DATE_SUB('2017-01-01', 14) //判断用户访问时间in_time大于等于“当前时间2017-01-01减去14天的”结果值并且小于等于当前时间2017-01-01,那么表示是在近15天之内访问的,便返回1,最终用于统计近15天PC端访问次数
              AND in_time <= '2017-01-01' 
              THEN 1 
            END
          ) dat_15,    --近15天pc端访问次数
          (
            CASE
              WHEN in_time >= DATE_SUB('2017-01-01', 29) //判断用户访问时间in_time大于等于“当前时间2017-01-01减去29天的”结果值并且小于等于当前时间2017-01-01,那么表示是在近30天之内访问的,便返回1,最终用于统计近30天PC端访问次数
              AND in_time <= '2017-01-01' 
              THEN 1 
            END
          ) dat_30,    --近30天pc端访问次数
          (
            CASE
              WHEN in_time >= DATE_SUB('2017-01-01', 59) 
              AND in_time <= '2017-01-01' 
              THEN 1 
            END
          ) dat_60,    --近60天pc端访问次数
          (
            CASE
              WHEN in_time >= DATE_SUB('2017-01-01', 89) 
              AND in_time <= '2017-01-01' 
              THEN 1 
            END
          ) dat_90,    --近90天pc端访问次数
          hour(in_time) visit_hour, //通过 HOUR(具体日期时间) 获取具体日期时间的小时数字,最终用于统计某个时间段的访问次数
          //排序函数:row_number() over(distribute by(分桶字段名) sort by(排序字段名 ASC/DESC))
          row_number() over(distribute BY a.user_id sort BY a.in_time DESC) rn_desc, //获取rn_desc列值的序号ID为1的话,表示获取用户近90天之内最近访问时间
          row_number() over(distribute BY a.user_id sort BY a.in_time ASC) rn_asc  //获取rn_desc列值的序号ID为1的话,表示获取用户近90天之内第一次访问时间
            FROM fdm.itcast_fdm_user_pc_pageview a  //pc端的用户访问记录
            // 前第90天 <= in_time <= 昨天:当前用户访问记录时间 大于等于 “当前时间2017-01-01 减去 89天的”结果值,并且小于等于当前时间2017-01-01 
            // 第一版本:没有使用“where dt >= 前第90天”,而是使用“前第90天 <= in_time <= 昨天”,同样可以统计 近90天之内的表数据
            // 第二版本(推荐):使用“where dt >= 前第90天”,即 where dt >= date_add('2017-01-01', -29),可以达到更加快速地搜索查询表数据
            // WHERE in_time >= DATE_ADD('2017-01-01', -89) AND in_time <= '2017-01-01' 
        WHERE dt >= date_add('2017-01-01', -29)
          ) pc ON (t.user_id = pc.user_id) 
    LEFT JOIN 
           (SELECT user_id,
          sum(
            CASE
              WHEN TYPE = 'visit_ip' 
              THEN cnt //返回一个月中 不同IP地址对应的总记录数
            END
          ) month1_pc_diff_ip_cnt,  //上述返回的 数据值作为 指标名称为 近30天PC端访问的不同IP数量
          MAX(     //此处使用MAX()没有任何业务意义,因为使用了GROUP BY,因此为了语法不报错,所以才使用了MAX()等聚合函数来补全语法
            CASE
              WHEN TYPE = 'visit_ip' and rn= 1 //获取排序分组中rn编号值为1的数据 表示获取最常用的IP地址。itcast_gdm_user_visit_temp_01临时表中对分组中数据使用的是desc降序,因此rn=1获取的是最大值。
              THEN con //返回一个月中 使用次数最多的 IP地址字段的值
            END
          ) month1_pc_common_ip,   //上述返回的 数据值 作为 指标名称为 近30天PC端访问的最常用的IP 
          sum(
            CASE
              WHEN TYPE = 'cookie_id'  //返回一个月中 不同cookie对应的总记录数
              THEN cnt //返回一个月中 不同cookie对应的总记录数
            END
          ) month1_pc_diff_cookie_cnt,//上述返回的 数据值作为 指标名称为 近30天PC端访问的不同cookie的数量
          MAX(
            CASE
              WHEN TYPE = 'cookie_id' and rn = 1//获取排序分组中rn编号值为1的数据 表示获取最常用的cookie。itcast_gdm_user_visit_temp_01临时表中对分组中数据使用的是desc降序,因此rn=1获取的是最大值。
              THEN con //返回一个月中 使用次数最多的 CookieID字段的值
            END
          ) month1_pc_common_cookie, //上述返回的 数据值作为 指标名称为 近30天PC端访问的最常用的cookie
          MAX(
            CASE
              WHEN TYPE = 'browser_name' and rn = 1//获取排序分组中rn编号值为1的数据 表示获取最常用的浏览器。itcast_gdm_user_visit_temp_01临时表中对分组中数据使用的是desc降序,因此rn=1获取的是最大值。
              THEN con //返回一个月中 使用次数最多的 浏览器名字
            END
          ) month1_pc_common_browser_name,//上述返回的 数据值作为 指标名称为 近30天PC端访问的最常用的浏览器
          MAX(
            CASE
              WHEN TYPE = 'visit_os' and rn = 1//获取排序分组中rn编号值为1的数据 表示获取最常用的操作系统。itcast_gdm_user_visit_temp_01临时表中对分组中数据使用的是desc降序,因此rn=1获取的是最大值。
              THEN con //返回一个月中 使用次数最多的 操作系统名字
            END
          ) month1_pc_common_os //上述返回的 数据值作为 指标名称为 近30天PC端访问的最常用的操作系统
        FROM gdm.itcast_gdm_user_visit_temp_01 
        GROUP BY user_id
            ) b ON (t.user_id = b.user_id) 
    LEFT JOIN 
            (SELECT a.*,
          (
            CASE
              WHEN log_time >= DATE_SUB('2017-01-01', 6) 
              AND log_time <= '2017-01-01' 
              THEN 1 
            END
          ) dat_7,    --近7天app端访问次数
          (
            CASE
              WHEN log_time >= DATE_SUB('2017-01-01', 14) 
              AND log_time <= '2017-01-01' 
              THEN 1 
            END
          ) dat_15,    --近15天app端访问次数
          (
            CASE
              WHEN log_time >= DATE_SUB('2017-01-01', 29) 
              AND log_time <= '2017-01-01' 
              THEN 1 
            END
          ) dat_30,    --近30天app端访问次数
          (
            CASE
              WHEN log_time >= DATE_SUB('2017-01-01', 59) 
              AND log_time <= '2017-01-01' 
              THEN 1 
            END
          ) dat_60,    --近60天app端访问次数
          (
            CASE
              WHEN log_time >= DATE_SUB('2017-01-01', 89) 
              AND log_time <= '2017-01-01' 
              THEN 1 
            END
          ) dat_90,    --近90天app端访问次数
          //排序函数:row_number() over(distribute by(分桶字段名) sort by(排序字段名 ASC/DESC))
          row_number() over (distribute BY a.user_id sort BY a.log_time DESC) rn_desc, //当取 where rn_desc = 1 时表示取出每个分桶中的第一条数据,代表近90天之内最近一次的访问时间
          row_number() over (distribute BY a.user_id sort BY a.log_time ASC) rn_asc  //当取 where rn_asc= 1 时表示取出每个分桶中的第一条数据,代表近90天之内第一次访问时间
            FROM fdm.itcast_fdm_user_app_pageview a  //app端的客户访问信息表
            // 前第90天 <= log_time <= 昨天:当前用户访问记录时间 大于等于 “当前时间2017-01-01 减去 89天的”结果值,并且小于等于当前时间2017-01-01 
            // 第一版本:没有使用“where dt >= 前第90天”,而是使用“前第90天 <= log_time <= 昨天”,同样可以统计 近90天之内的表数据
            // 第二版本(推荐):使用“where dt >= 前第90天”,即 where dt >= date_add('2017-01-01', -29),可以达到更加快速地搜索查询表数据
            // WHERE log_time >= DATE_ADD('2017-01-01', -89) AND log_time <= '2017-01-01' 
        WHERE dt >= date_add('2017-01-01', -29)
         ) app ON (t.user_id = app.user_id) GROUP BY t.user_id ;

猜你喜欢

转载自blog.csdn.net/zimiao552147572/article/details/88427426