Python工业项目实战 06:数仓主题应用层ST层构建

Posted 黑马程序员官方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python工业项目实战 06:数仓主题应用层ST层构建相关的知识,希望对你有一定的参考价值。

知识点01:课程回顾

  1. 数仓主题设计中有哪些主题,以及每个主题的核心指标有哪些?

    • DWB:轻度汇总层:基于每个主题,构建主题事务事实表
      • 关联:按照主题,将主题需要用到的字段合并到一张表
      • 聚合:基础聚合,构建一些基础指标
    • 呼叫中心主题:派工次数、回退工单、作废工单
    • 工单主题:待派工、处理中、完成工单
    • 油站主题:总油站个数、新增油站个数、停用油站个数
    • 安装主题:联调安装、全新安装、是否收费
    • 维修主题:维修工单、零件个数、设备个数
    • 差旅主题:报销金额、车船费用、住宿费用
  2. 更正呼叫中心事实主题

    insert overwrite table one_make_dwb.fact_call_service partition (dt = '20210101')
    select
        call.id     --来电受理唯一id
        , call.code -- 受理单唯一编码
        , date_format(timestamp(call.call_time), 'yyyymmdd') as call_date -- 来电日期(日期id)
        , hour(timestamp(call.call_time))  -- 来电时间(小时)(事实维度)
        , call.call_type -- 来电类型(事实维度)
        , call_dict.dictname -- 来电类型名称(事实维度)
        , call.process_way -- 受理方式(事实维度)
        , process_dict.dictname -- 受理方式(事实维度)
        , call.call_oilstation_id -- 油站id
        , call.accept_userid -- 受理人员id
        , 1 -- 单据数量(指标列)
        , case when call.process_way = 5  then 1 else 0 end -- 派工数量:0-自己处理,1-产生派工
        , case when workorder.status = -1 then 1 else 0 end -- 派工单作废数量
        , case when workorder.status = -2 then 1 else 0 end -- 派工单退单数量
        --floor(to_unix_timestamp(timestamp(call.process_time),'yyyy-mm-dd hh:mm:ss') - to_unix_timestamp(timestamp(call.call_time), 'yyyy-mm-dd hh:mm:ss') / 1000.0) -- 受理时长(单位:秒)
    	, floor((call.process_time - call.call_time ) / 1000)  -- 受理时长(单位:秒)
        , case when call.call_type = 5 then 1 else 0 end -- 电话支持数量
        , case when call.call_type in (1, 2, 3, 4) then 1 else 0 end -- 现场安装、维修、改造、巡检数量
        , case when call.call_type = 7 then 1 else 0 end -- 回访单据数量
        , case when call.call_type = 8 then 1 else 0 end -- 投诉单据数量
        , case when call.call_type = 9 or call.call_type = 6 then 1 else 0 end -- 其他业务单据数量
    -- 来电详情表
    from one_make_dwd.ciss_service_callaccept call
    -- 字典信息表:得到来电类型名称
    left join one_make_dwb.tmp_dict call_dict on call.call_type = call_dict.dictid  and call_dict.dicttypename = '来电类型'
    -- 字典信息表:受理方式名称
    left join one_make_dwb.tmp_dict process_dict on call.process_way = process_dict.dictid and process_dict.dicttypename = '来电受理单--处理方式'
    -- 工单信息表:得到工单状态:-2:退单,-1:作废
    left join one_make_dwd.ciss_service_workorder workorder on workorder.dt = '20210101' and workorder.callaccept_id = call.id
    where call.dt = '20210101' and call.code != 'null' and call.call_time is not null;
    
  3. 问题

    • 主题、维度、表很多,关系也很复杂,课后怎么去梳理?

      • step1:表结构和字段:10个字段
        • 对字段进行分类:工单、费用、呼叫中心、油站
        • 这张表的作用:熟悉业务
      • step2:看业务数据表:desc
        • 找每张表中有没有对应字段:大部分字段
        • 相关联的业务表:小部分字段
      • step3:每张表之间的关系
      • step4:子查询 + Join
    • 工作中如何开发SparkSQL实现ETL的需求等等?

      • ETL => DSL + SQL

      • DSL:函数式编程:RDD算子 + DSL函数

        • df.map.filter.flatMap.select.where.groupBy
      • SQL:提交SQL语句

        # todo:1-构建SparkSession
        spark = SparkSession.setMaster.appName
        
        //todo:2-处理逻辑
        //step1:读取数据
        inputData = spark.read.text(Path)
        //step2:处理数据
        rsData = inputData.map.flatMap……
        //step3:保存结果
        rsData.write.saveAsTable()
        spark.sql("")
        
        # todo:3-关闭资源
        spark.stop
        
        sc =SparkContext
        # 建库
        # 构建连接SparkSQL:pySpark ,pyHive
        conn.cursor.execute(sql)
        
      • 工具使用

        • DataGrip:可视化数据库交互工具:测试开发
          • SQL测试
        • PyCharm | IDEA:所有代码在这里开发:测试开发
        • 运行:将代码打包到集群运行
          • spark-submit jar file | python file
          • ThirftServer

知识点02:课程目标

  1. 构建ST层:数据应用层
    • 掌握每个主题的聚合指标和聚合的维度
    • 工单主题
    • 油站主题
    • 回访主题
    • 安装主题
    • 费用主题
  2. DM层的设计
    • 运营部门需要的数据抽取

知识点03:数仓分层回顾

  • 目标:回顾一站制造项目分层设计

  • 实施

    • ODS层 :原始数据层:原始事务事实表
    • DWD层:明细数据层:原始事务事实表
    • DWS层:维度数据层:维度数据表
    • DWB层:轻度聚合层:主题事务事实表
    • ST层:数据应用层:主题周期快照表
      • 报表
    • DM层:数据集市层:每个部门需求的数据
      • 部门其他数据应用
  • 小结

    • 回顾一站制造项目分层设计

知识点04:ST层的设计

  • 目标掌握ST层的设计

  • 路径

    • step1:功能
    • step2:来源
    • step3:需求
  • 实施

    • 功能:数据应用层,用于支撑对外所有主题的报表应用数据的结果

      • 对外提供整个公司所有运营的报表
    • 来源:对DWB层的主题事实数据关联DWS层的维度表进行最终聚合

      • DWS:维度表:时间、地区、油站、组织机构

        维度id	维度值
        
      • DWB:工单、呼叫中心、费用

        维度id	指标
        
    • 需求:按照一站制造的业务主题的划分需求,构建每个主题的ST层的数据

      维度id	维度值		聚合指标
      
  • 小结

    • 掌握ST层的设计

知识点05:服务域:工单主题分析

  • 目标掌握工单主题的需求分析

  • 路径

    • step1:需求
    • step2:分析
  • 实施

    • 需求:统计不同维度下的工单主题指标的结果

      字段名称字段说明来源
      owner_process派工方式-自己处理数量one_make_dwb.fact_call_service
      tran_process派工方式-转派工数量one_make_dwb.fact_call_service
      wokerorder_num工单总数one_make_dwb.fact_worker_order
      wokerorder_num_max工单总数最大值one_make_dwb.fact_worker_order
      wokerorder_num_min工单总数最小值one_make_dwb.fact_worker_order
      wokerorder_num_avg工单总数平均值one_make_dwb.fact_worker_order
      install_sumnum派工类型-安装总数one_make_dwb.fact_worker_order
      repair_sumnum派工类型-维修总数one_make_dwb.fact_worker_order
      remould_sumnum派工类型-巡检总数one_make_dwb.fact_worker_order
      inspection_sumnum派工类型-改造总数one_make_dwb.fact_worker_order
      alread_complete_sumnum完工总数one_make_dwb.fact_worker_order
      customer_classify_zsh客户类型-中石化数量one_make_dws.dim_oilstation
      customer_classify_jxs客户类型-经销商数量one_make_dws.dim_oilstation
      customer_classify_qtzx客户类型-其他直销数量one_make_dws.dim_oilstation
      customer_classify_zsy客户类型-中石油数量one_make_dws.dim_oilstation
      customer_classify_qtwlh客户类型-其他往来户数量one_make_dws.dim_oilstation
      customer_classify_zhjt客户类型-中化集团数量one_make_dws.dim_oilstation
      customer_classify_zhy客户类型-中海油数量one_make_dws.dim_oilstation
      customer_classify_gys客户类型-供应商数量one_make_dws.dim_oilstation
      customer_classify_onemake客户类型-一站制造**数量one_make_dws.dim_oilstation
      customer_classify_fwy客户类型-服务员数量one_make_dws.dim_oilstation
      customer_classify_zt客户类型-中铁数量one_make_dws.dim_oilstation
      customer_classify_hzgs客户类型-合资公司数量one_make_dws.dim_oilstation
      customer_classify_jg客户类型-军供数量one_make_dws.dim_oilstation
      customer_classify_zhhangy客户类型-中航油数量one_make_dws.dim_oilstation
      dws_day string日期维度-按天one_make_dws.dim_date
      dws_week string日期维度-按周one_make_dws.dim_date
      dws_month string日期维度-按月one_make_dws.dim_date
      oil_type string油站类型one_make_dws.dim_oilstation
      oil_province油站所属省one_make_dws.dim_oilstation
      oil_city string油站所属市one_make_dws.dim_oilstation
      oil_county string油站所属区one_make_dws.dim_oilstation
      customer_classify客户类型one_make_dws.dim_oilstation
      customer_province客户所属省one_make_dws.dim_oilstation
      • 呼叫中心主题事实
    • 分析

      • 指标

        • 工单自处理个数、工单转派工个数
        • 工单总数、最大值、最小值、平均值
        • 安装总数、维修总数、巡检总数、改造总数、完工总数
        • 中石化数量、经销商数量、其他直销数量、中石油数量、其他往来户数量、中化集团数量、中海油数量
        • 供应商数量、一站制造数量、服务工程师数量、中铁数量、合资公司数量、军供数量、中航油数量
      • 维度

        • 日期维度:天、周、月
        • 油站维度:类型、省份、城市、地区
        • 客户维度:类型、省份
      • 数据表

        • 事实表

          • fact_worker_order:工单事实表

            select
                wo_num, --工单数量
                callaccept_id,--来电受理单id
                oil_station_id, --油站id
                dt --日期
            

          from fact_worker_order;

          
          
          
          - fact_call_service:呼叫中心事实表
          
          ```sql
          select
              id,--来电受理单id
            process_way_name --处理方式
          from fact_call_service;  
          

          [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KMnBhIub-1672022216324)(Day1013_数仓主题应用层ST层构建.assets/image-20211013101145353.png)]

      • 维度表

        • dim_oilstation:油站维度表

          select
              id,--油站id
              company_name,--公司名称
              province_name,--省份名称
              city_name,--城市名称
              county_name,--区域名称
              customer_classify_name,--客户名称
              customer_province_name--客户省份
          from dim_oilstation;
          
        • dim_date:时间维度表

          select
              date_id,--天
              week_in_year_id,--周
            year_month_id --月
          from dim_date;
          

    • 实现分析【不能运行】

      -- 工单事实表
      select
          sum(case when b.process_way_name = '自己处理' then 1 else 0 end) as own,
          sum(case when b.process_way_name = '转派工' then 1 else 0 end) as other,
          sum(a.wo_num), --工单数量
          max(a.wo_num),
          min(a.wo_num),
          avg(a.wo_num),
          sum(a.install_num),
          sum(a.repair_num),
          sum(a.remould_num),
          sum(a.inspection_num),
          sum(a.alread_complete_num),
          sum(case when c.customer_classify_name = '中石化' then 1 else 0 end) as zsy_count,
          ……
          a.callaccept_id,--来电受理单id
          c.id, --油站id
          c.company_name,--公司名称
          c.province_name,--省份名称
          c.city_name,--城市名称
          c.county_name,--区域名称
          c.customer_classify_name,--客户名称
          c.customer_province_name ,--客户省份
          d.date_id,--天
          d.week_in_year_id,--周
          d.year_month_id --月
      from fact_worker_order a
      left join fact_call_service b on a.callaccept_id = b.id
      left join one_make_dws.dim_oilstation c on a.oil_station_id = c.id
      left join one_make_dws.dim_date d on a.dt = d.date_id
      group by
          c.id, --油站id
          c.company_name,--公司名称
          c.province_name,--省份名称
          c.city_name,--城市名称
          c.county_name,--区域名称
          c.customer_classify_name,--客户名称
          c.customer_province_name ,--客户省份
          d.date_id,--天
          d.week_in_year_id,--周
          d.year_month_id; --月;
      
  • 小结

    • 掌握工单主题的需求分析

知识点06:服务域:工单主题实现

  • 目标实现工单主题表的维度指标构建

  • 实施

    • 建库

      create database if not exists one_make_st;
      
    • 建表

      -- 创建工单主题表
      drop table if exists one_make_st.subj_worker_order;
      create table if not exists one_make_st.subj_worker_order(
          owner_process bigint comment '派工方式-自己处理数量'
          ,tran_process bigint comment '派工方式-转派工数量'
          ,wokerorder_num bigint comment '工单总数'
          ,wokerorder_num_max int comment '工单总数最大值'
          ,wokerorder_num_min int comment '工单总数最小值'
          ,wokerorder_num_avg int comment '工单总数平均值'
          ,install_sumnum bigint comment '派工类型-安装总数'
          ,repair_sumnum bigint comment '派工类型-维修总数'
          ,remould_sumnum bigint comment '派工类型-巡检总数'
          ,inspection_sumnum bigint comment '派工类型-改造总数'
          ,alread_complete_sumnum bigint comment '完工总数'
          ,customer_classify_zsh bigint comment '客户类型-中石化数量'
          ,customer_classify_jxs bigint comment '客户类型-经销商数量'
          ,customer_classify_qtzx bigint comment '客户类型-其他直销数量'
          ,customer_classify_zsy bigint comment '客户类型-中石油数量'
          ,customer_classify_qtwlh bigint comment '客户类型-其他往来户数量'
          ,customer_classify_zhjt bigint comment '客户类型-中化集团数量'
          ,customer_classify_zhy bigint comment '客户类型-中海油数量'
          ,customer_classify_gys bigint comment '客户类型-供应商数量'
          ,customer_classify_onemake bigint comment '客户类型-一站制造**数量'
          ,customer_classify_fwy bigint comment '客户类型-服务员数量'
          ,customer_classify_zt bigint comment '客户类型-中铁数量'
          ,customer_classify_hzgs bigint comment '客户类型-合资公司数量'
          ,customer_classify_jg bigint comment '客户类型-军供数量'
          ,customer_classify_zhhangy bigint comment '客户类型-中航油数量'
          ,dws_day string comment '日期维度-按天'
          ,dws_week string comment '日期维度-按周'
          ,dws_month string comment '日期维度-按月'
          ,oil_type string comment '油站维度-油站类型'
          ,oil_province string comment '油站维度-油站所属省'
          ,oil_city string comment '油站维度-油站所属市'
          ,oil_county string comment '油站维度-油站所属区'
          ,customer_classify string comment '客户维度-客户类型'
          ,customer_province string comment '客户维度-客户所属省'
      ) comment '工单主题表'
      partitioned by (month String, week String, day String)
      stored as orc
      location '/data/dw/st/one_make/subj_worker_order'
      ;
      
    • 构建

      insert overwrite table one_make_st.subj_worker_order partition(month = '202101', week='2021W1', day='20210101')
      select
          sum(case when fcs.process_way_name = '自己处理' then 1 else 0 end) owner_process, --工单自处理个数
      	sum(case when fcs.process_way_name = '转派工' then 1 else 0 end) tran_process,    --工单转派工个数
      	sum(fwo.wo_num) wokerorder_num,                                      --工单总数
      	max(fwo.wo_num) wokerorder_num_max,                                  --最大值
          min(fwo.wo_num) wokerorder_num_min,                                  --最小值
      	avg(fwo.wo_num) wokerorder_num_avg,                                  --平均值
      	sum(fwo.install_num) install_sumnum,                                     --安装总数
      	sum(fwo.repair_num) repair_sumnum,                                       --维修总数
          sum(fwo.remould_num) remould_sumnum,                                     --巡检总数
      	sum(fwo.inspection_num) inspection_sumnum,                               --改造总数
      	sum(fwo.alread_complete_num) alread_complete_sumnum,                     --完工总数
          sum(case when oil.customer_classify_name ='中石化' then 1 else 0 end) customer_classify_zsh,       --中石化数量
      	sum(case when oil.customer_classify_name ='经销商' then 1 else 0 end) customer_classify_jxs,       --经销商数量
          sum(case when oil.customer_classify_name ='其他直销' then 1 else 0 end) customer_classify_qtzx,      --其他直销数量
      	sum(case when oil.customer_classify_name ='中石油' then 1 else 0 end) customer_classify_zsy,       --中石油数量
          sum(case when oil.customer_classify_name ='其他往来户' then 1 else 0 end) customer_classify_qtwlh,     --其他往来户数量
      	sum(case when oil.customer_classify_name ='中化集团' then 1 else 0 end) customer_classify_zhjt,      --中化集团数量
          sum(case when oil.customer_classify_name ='中海油' then 1 else 0 end) customer_classify_zhy,       --中海油数量
      	sum(case when oil.customer_classify_name ='供应商' then 1 else 0 end) customer_classify_gys,        --供应商数量
          sum(case when oil.customer_classify_name ='一站制造**' then 1 else 0 end) customer_classify_onemake,     --一站制造数量
      	sum(case when oil.customer_classify_name ='服务工程师' then 1 else 0 end) customer_classify_fwy,          --服务工程师数量
          sum(case when oil.customer_classify_name ='中铁' then 1 else 0 end) customer_classify_zt,           --中铁数量
      	sum(case when oil.customer_classify_name ='合资公司' then 1 else 0 end) customer_classify_hzgs,         --合资公司数量
          sum(case when oil.customer_classify_name ='军供' then 1 else 0 end) customer_classify_jg,             --军供数量
      	sum(case when oil.customer_classify_name ='中航油' then 1 else 0 end) customer_classify_zhhangy,         --中航油数量
          dd.date_id dws_day,                                                  --时间天
      	dd.week_in_year_id dws_week,                                         --时间周
      	dd.year_month_id dws_month,                                          --时间月
      	oil.company_name oil_type,                                           --油站类型
      	oil.province_name oil_province,                                      --油站省份
          oil.city_name oil_city,                                              --油站城市
      	oil.county_name oil_county,                                          --油站地区
      	oil.customer_classify_name customer_classify,                        --客户类型
      	oil.customer_province_name customer_province                         --客户省份
      --工单事务事实表
      from one_make_dwb.fact_worker_order fwo
      --获取自处理个数,转派单个数
      left join one_make_dwb.fact_call_service fcs on fwo.callaccept_id = fcs.id
      --关联日期维度
      left join one_make_dws.dim_date dd on fwo.dt = dd.date_id
      --关联油站维度
      left join one_make_dws.dim_oilstation oil on fwo.oil_station_id = oil.id
      where dd.year_month_id = '202101'and dd.week_in_year_id = '2021W1' and  dd.date_id = '20210101'
      --按照维度字段分组
      group by dd.date_id, dd.week_in_year_id, dd.year_month_id, oil.company_name, oil.province_name, oil.city_name, oil.county_name,oil.customer_classify_name, oil.customer_province_name
      ;
      
  • 小结

    • 实现工单主题表的维度指标构建

知识点07:服务域:油站主题分析

  • 目标掌握油站主题的需求分析

  • 路径

    • step1:需求
    • step2:分析
  • 实施

    • 需求:统计不同维度下的油站主题指标的结果

  • 分析

    • 指标:油站数量、新增油站数量

    • 维度

      • 日期维度:天、周、月
      • 油站维度:类型、省份、城市、地区
      • 客户维度:类型、省份
    • 数据表

      • 事实表

        • fact_oil_station:油站事实表

          select
              os_num,--油站个数
              current_new_os_num --新增油站个数
          from fact_oil_station;
          
      • 维度表

        • dim_oilstation:油站维度表

          select
              id,--油站id
              company_name,--公司名称
              province_name,--省份名称
              city_name,--城市名称
              county_name,--区域名称
              customer_classify_name,--客户名称
              customer_province_name--客户省份
          from dim_oilstation;
          
        • dim_date:时间维度表

          select
              date_id,--天
              week_in_year_id,--周
              year_month_id --月
          from dim_date;
          
      • 实现分析

        select
            a.os_id,--油站id
            sum(a.os_num),--油站数量
            sum(a.current_new_os_num),--新增油站数量
            b.date_id,--天
            b.week_in_year_id,--周
            b.year_month_id, --月
            c.company_name,--公司名称
            c.province_name,--省份名称
            c.city_name,--城市名称
            c.county_name,--区域名称
            c.customer_classify_name,--客户名称
            c.customer_province_name--客户省份
        from fact_oil_station a
        join one_make_dws.dim_date b on a.dt = b.date_id
        join one_make_dws.dim_oilstation c on a.os_id = c.id
        group by
            b.date_id,--天
            b.week_in_year_id,--周
            b.year_month_id, --月
            c.company_name,--公司名称
            c.province_name,--省份名称
            c.city_name,--城市名称
            c.county_name,--区域名称
            c.customer_classify_name,--客户名称
            c.customer_province_name;--客户省份;
        
  • 小结

    • 掌握油站主题的需求分析

知识点08:服务域:油站主题实现

  • 目标实现油站主题表的维度指标构建

  • 实施

    • 建表

      -- 创建油站主题表
      drop table if exists one_make_st.subj_oilstation;
      create table if not exists one_make_st.subj_oilstation(
          sum_osnum bigint comment '油站数量'
          ,sumnew_osnum int comment '新增油站数量'
          ,dws_day string comment '日期维度-按天'
          ,dws_week string comment '日期维度-按周'
          ,dws_month string comment '日期维度-按月'
          ,oil_type string comment '油站维度-油站类型'
          ,oil_province string comment '油站维度-油站所属省'
          ,oil_city string comment '油站维度-油站所属市'
          ,oil_county string comment '油站维度-油站所属区'
          ,customer_classify string comment '客户维度-客户类型'
          ,customer_province string comment '客户维度-客户所属省'
      ) comment '油站主题表'
      partitioned by (month String, week String, day String)
      stored as orc
      location '/data/dw/st/one_make/subj_oilstation';
      
    • 构建

      insert overwrite table one_make_st.subj_oilstation partition(month = '202101', week='2021W1', day='20210101')
      select
          sum(oil.os_num) sum_osnum,                          --油站数量
      	sum(oil.current_new_os_num) sumnew_osnum,           --新增油站数量
          dd.date_id dws_day,                                 --日期天
      	dd.week_in_year_id dws_week,                        --日期周
      	dd.year_month_id dws_month,                         --日期月
          dimoil.company_name oil_type,                       --油站类型
      	dimoil.province_name oil_province,                  --油站省份
      	dimoil.city_name oil_city,                          --油站城市
          dimoil.county_name oil_county,                      --油站区域
      	dimoil.customer_classify_name customer_classify,    --客户类型
          dimoil.customer_province_name customer_province     --客户省份
      --油站事务事实表
      from one_make_dwb.fact_oil_station oil
      --关联日期维度表
      以上是关于Python工业项目实战 06:数仓主题应用层ST层构建的主要内容,如果未能解决你的问题,请参考以下文章

      Python工业项目实战02:数仓设计及数据采集

      Python工业项目实战01:项目介绍及环境构建

      Python工业项目实战 04:数仓维度层DWS层构建

      Python工业项目实战:服务器性能监控Prometheus及项目总结

      Python工业项目实战03:ODS层及DWD层构建

      数仓建设 | ODSDWDDWM等理论实战(好文收藏)