hive实战项目:旅游集市数仓建设

news2024/11/27 0:26:39

旅游集市数仓建设

文章目录

  • 旅游集市数仓建设
      • 为什么要设计数据分层?
      • 分层设计
        • ODS(Operational Data Store):数据运营层
        • DW(Data Warehouse):数据仓库层
          • DWD(Data Warehouse Detail):数据明细层
          • DWM(Data Warehouse Middle):数据中间层
          • DWS(Data Warehouse Service):数据服务层
        • ADS/APP/DM(Application Data Store/Application/DataMarket):数据应用层/数据集市
        • DIM(Dimension):维表层
      • 可能会用到的一些UDF
        • 添加资源并注册函数
        • get_points
        • dateBetweenUDF
        • calLength
        • get_city_or_prov_id
      • 涉及到的一些表:
        • ODS层
          • ods_oidd
          • ods_wcdr
          • ods_ddr
          • ods_dpi
        • DWD层:
          • dwd_res_regn_mergelocation_msk_d
            • mergeSQL
          • dwm_staypoint_msk_d
            • SQL
          • dws_province_tourist_msk_d
          • dws_city_tourist_msk_d
          • dws_county_tourist_msk_d
            • SQL
        • DIM层
          • dim_usertag_msk_m
        • ADS层
      • 需求矩阵
        • 根据省游客表计算如下指标
        • 根据市游客表计算如下指标
        • 根据区县游客表计算如下指标

为什么要设计数据分层?

作为一名数据的规划者,我们肯定希望自己的数据能够有秩序地流转,数据的整个生命周期能够清晰明确被设计者和使用者感知到。直观来讲就是如下的左图这般层次清晰、依赖关系直观。

但是,大多数情况下,我们完成的数据体系却是依赖复杂、层级混乱的。如下的右图,在不知不觉的情况下,我们可能会做出一套表依赖结构混乱,甚至出现循环依赖的数据体系。

​ 因此,我们需要一套行之有效的数据组织和管理方法来让我们的数据体系更有序,这就是谈到的数据分层。数据分层并不能解决所有的数据问题,但是,数据分层却可以给我们带来如下的好处:

  • 清晰数据结构:每一个数据分层都有它的作用域和职责,在使用表的时候能更方便地定位和理解

  • 减少重复开发:规范数据分层,开发一些通用的中间层数据,能够减少极大的重复计算

  • 统一数据口径:通过数据分层,提供统一的数据出口,统一对外输出的数据口径

  • 复杂问题简单化:将一个复杂的任务分解成多个步骤来完成,每一层解决特定的问题

分层设计

image.png
ODS(Operational Data Store):数据运营层

​ “面向主题的”数据运营层,也叫ODS层,是最接近数据源中数据的一层,数据源中的数据,经过抽取、洗净、传输,也就说传说中的 ETL 之后,装入本层。本层的数据,总体上大多是按照源头业务系统的分类方式而分类的。

一般来讲,为了考虑后续可能需要追溯数据问题,因此对于这一层就不建议做过多的数据清洗工作,原封不动地接入原始数据即可,至于数据的去噪、去重、异常值处理等过程可以放在后面的DWD层来做。

DW(Data Warehouse):数据仓库层

​ 数据仓库层是我们在做数据仓库时要核心设计的一层,在这里,从 ODS 层中获得的数据按照主题建立各种数据模型。DW层又细分为 DWD(Data Warehouse Detail)层、DWM(Data WareHouse Middle)层和DWS(Data Warehouse Service)层。

  • DWD(Data Warehouse Detail):数据明细层

​ 该层一般保持和ODS层一样的数据粒度,并且提供一定的数据质量保证。同时,为了提高数据明细层的易用性,该层会采用一些维度退化手法,将维度退化至事实表中,减少事实表和维表的关联。

  • DWM(Data Warehouse Middle):数据中间层

​ 该层会在DWD层的数据基础上,对数据做轻度的聚合操作,生成一系列的中间表,提升公共指标的复用性,减少重复加工。直观来讲,就是对通用的核心维度进行聚合操作,算出相应的统计指标。

  • DWS(Data Warehouse Service):数据服务层

​ 又称宽表。按照业务划分,如流量、订单、用户等,生成字段比较多的宽表,用于提供后续的业务查询,OLAP分析,数据分发等。

​ 一般来讲,该层的数据表会相对比较少,一张表会涵盖比较多的业务内容,由于其字段较多,因此一般也会称该层的表为宽表。在实际计算中,如果直接从DWD或者ODS计算出宽表的统计指标,会存在计算量太大并且维度太少的问题,因此一般的做法是,在DWM层先计算出多个小的中间表,然后再拼接成一张DWS的宽表。由于宽和窄的界限不易界定,也可以去掉DWM这一层,只留DWS层,将所有的数据在放在DWS亦可。

ADS/APP/DM(Application Data Store/Application/DataMarket):数据应用层/数据集市

​ 在这里,主要是提供给数据产品和数据分析使用的数据,一般会存放在 ES、PostgreSql、Redis等系统中供线上系统使用,也可能会存在 Hive 或者 Druid 中供数据分析和数据挖掘使用。比如我们经常说的报表数据,一般就放在这里。

DIM(Dimension):维表层

维表层主要包含两部分数据:

  • 高基数维度数据:一般是用户资料表、商品资料表类似的资料表。数据量可能是千万级或者上亿级别。

  • 低基数维度数据:一般是配置表,比如枚举值对应的中文含义,或者日期维表。数据量可能是个位数或者几千几万。

image.png

可能会用到的一些UDF

添加资源并注册函数
add jars /root/hive-1.0.jar;
create temporary function get_points as 'ctyun.udf.getPointsUDF';
create temporary function dateBetweenUDF as 'ctyun.udf.dateBetweenUDF';
create temporary function calLength as 'ctyun.udf.calLength';
create temporary function get_city_or_prov_id as 'ctyun.udf.getCityIdOrProvID';
get_points

传入网格id:grid_id,返回网格中心的经度、纬度

示例:select get_points(“845040”)[0] as longitude,get_points(“845040”)[1] as latitude;

package ctyun.udf;

import ctyun.udf.grld.Grid;
import org.apache.hadoop.hive.ql.exec.UDF;

import java.awt.geom.Point2D;
import java.lang.reflect.Array;
import java.util.ArrayList;

public class getPointsUDF extends UDF {
    public ArrayList<Double> evaluate(String grid_id) {
        // 根据网格id 获取经纬度
        ArrayList<Double> cols = new ArrayList<Double>();
        Point2D.Double points = Grid.getCenter(Long.valueOf(grid_id));
        cols.add(points.x);
        cols.add(points.y);
        return cols;
    }
}
dateBetweenUDF

传入两个时间,返回时间差,单位:分

示例:select dateBetweenUDF(“20180503174500”, “20180503174000”);

package ctyun.udf;

import ctyun.udf.util.DateUtil;
import org.apache.hadoop.hive.ql.exec.UDF;

public class dateBetweenUDF extends UDF {
    public int evaluate(String grid_first_time,String grid_last_time) {
        // 获取两个时间字符串的差 单位:分
        return Math.abs(DateUtil.betweenM(grid_first_time,grid_last_time));
    }
}
calLength

传入两个网格id:grid_id,返回两个网格中心点的距离,单位:米

示例:select calLength(“845040”,“855040”);

package ctyun.udf;

import ctyun.udf.util.Geography;
import org.apache.hadoop.hive.ql.exec.UDF;

public class calLength extends UDF {
    public String evaluate(String grid_id, String resi_grid_id) {
        // 根据grid_id 网格id, resi_grid_id 居住地网格id 计算距离
        double distance = Geography.calculateLength(Long.valueOf(grid_id), Long.valueOf(resi_grid_id));
        return String.valueOf(distance);
    }
}
get_city_or_prov_id

传入县id,返回city_id或province_id

示例:

​ 返回city_id:

​ select get_city_or_prov_id(“8340104”,“city”);
​ 返回province_id:

​ select get_city_or_prov_id(“8340104”,“province”);

package ctyun.udf;

import ctyun.udf.util.SSXRelation;
import org.apache.hadoop.hive.ql.exec.UDF;

public class getCityIdOrProvID extends UDF {
    public String evaluate(String county_id, String param) {
        // 根据county_id获取 cityID or provinceID
        String id = "-1";
        if ("city".equals(param)) {
            id = SSXRelation.COUNTY_CITY.get(county_id);
        } else if ("province".equals(param)) {
            id = SSXRelation.COUNTY_PROVINCE.get(county_id);
        }
        return id;
    }
}

涉及到的一些表:

ODS层
ods_oidd

OIDD是采集A接口的信令数据,包括手机在发生业务时的位置信息。OIDD信令类型数据分为三大类,呼叫记录、短信记录和用户位置更新记录。

CREATE EXTERNAL TABLE IF NOT EXISTS ods.ods_oidd(
    mdn string comment '手机号码'  
    ,start_time string comment '业务开始时间'  
    ,county_id string comment '区县编码'  
    ,longi string comment '经度'  
    ,lati string comment '纬度'  
    ,bsid string comment '基站标识'  
    ,grid_id string comment '网格号'  
    ,biz_type string comment '业务类型'  
    ,event_type string comment '事件类型'  
    ,data_source string comment '数据源'  
) 
comment  'oidd位置数据表'
PARTITIONED BY (
    day_id string comment '天分区'  
) 
ROW FORMAT DELIMITED 
    FIELDS TERMINATED BY '\t' 
STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' 
    OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'  
location '/data/tour/ods/ods_oidd'; 

// 添加分区
alter table ods.ods_oidd add partition(day_id=20180503);
// 加载数据
load data local inpath '/usr/local/soft/ctyun/ods_oidd/day_id=20180503/*' into table ods.ods_oidd partition(day_id=20180503);
ods_wcdr

WCDR采集网络中ABIS接口的数据,基于业务发生过程中三个扇区的测量信息,通过三角定位法确定用户的位置信息。

CREATE EXTERNAL TABLE IF NOT EXISTS ods.ods_wcdr (
    mdn string comment '手机号码'  
    ,start_time string comment '业务开始时间'  
    ,county_id string comment '区县编码'  
    ,longi string comment '经度'  
    ,lati string comment '纬度'  
    ,bsid string comment '基站标识'  
    ,grid_id string comment '网格号'  
    ,biz_type string comment '业务类型'  
    ,event_type string comment '事件类型'  
    ,data_source string comment '数据源'  
) 
comment  'wcdr位置数据表'
PARTITIONED BY (
    day_id string comment '天分区'  
) 
ROW FORMAT DELIMITED 
    FIELDS TERMINATED BY '\t' 
STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' 
    OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'  
location '/data/tour/ods/ods_wcdr'; 

// 添加分区
alter table ods.ods_wcdr add partition(day_id=20180503);
// 加载数据
load data local inpath '/usr/local/soft/ctyun/ods_wcdr/day_id=20180503/*' into table ods.ods_wcdr partition(day_id=20180503);
ods_ddr

当前DDR中只有移动数据详单可以提取基站标识,其他语音,短信,增值等业务没有位置信息,不做为数据融合的基础数据。

CREATE EXTERNAL TABLE IF NOT EXISTS ods.ods_ddr(
    mdn string comment '手机号码'  
    ,start_time string comment '业务开始时间'  
    ,county_id string comment '区县编码'  
    ,longi string comment '经度'  
    ,lati string comment '纬度'  
    ,bsid string comment '基站标识'  
    ,grid_id string comment '网格号'  
    ,biz_type string comment '业务类型'  
    ,event_type string comment '事件类型'  
    ,data_source string comment '数据源'  
) 
comment  'ddr位置数据表'
PARTITIONED BY (
    day_id string comment '天分区'  
) 
ROW FORMAT DELIMITED 
    FIELDS TERMINATED BY '\t' 
STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' 
    OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'  
location '/data/tour/ods/ods_ddr'; 

// 添加分区
alter table ods.ods_ddr add partition(day_id=20180503);
// 加载数据
load data local inpath '/usr/local/soft/ctyun/ods_ddr/day_id=20180503/*' into table ods.ods_ddr partition(day_id=20180503);
ods_dpi

移动DPI数据数据采集用户移动用户数据上网时移动核心网和PDSN之间接口的数据。

CREATE EXTERNAL TABLE IF NOT EXISTS ods.ods_dpi(
    mdn string comment '手机号码'  
    ,start_time string comment '业务开始时间'  
    ,county_id string comment '区县编码'  
    ,longi string comment '经度'  
    ,lati string comment '纬度'  
    ,bsid string comment '基站标识'  
    ,grid_id string comment '网格号'  
    ,biz_type string comment '业务类型'  
    ,event_type string comment '事件类型'  
    ,data_source string comment '数据源'  
) 
comment  'dpi位置数据表'
PARTITIONED BY (
    day_id string comment '天分区'  
) 
ROW FORMAT DELIMITED 
    FIELDS TERMINATED BY '\t' 
STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' 
    OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'  
location '/data/tour/ods/ods_dpi'; 

// 添加分区
alter table ods.ods_dpi add partition(day_id=20180503);
// 加载数据	
load data local inpath '/usr/local/soft/ctyun/ods_dpi/day_id=20180503/*' into table ods.ods_dpi partition(day_id=20180503);
DWD层:
dwd_res_regn_mergelocation_msk_d

在ODS层中,由于数据来源不同,原始位置数据被分成了好几张表加载到了我们的ODS层。

为了方便大家的使用,我们在DWD层做了一张位置数据融合表,在这里,我们将oidd、wcdr、ddr、dpi位置数据汇聚到一张表里面,统一字段名,提升数据质量,这样就有了一张可供大家方便使用的明细表了。

CREATE EXTERNAL TABLE IF NOT EXISTS dwd.dwd_res_regn_mergelocation_msk_d (
    mdn string comment '手机号码'  
    ,start_time string comment '业务开始时间'  
    ,county_id string comment '区县编码'  
    ,longi string comment '经度'  
    ,lati string comment '纬度'  
    ,bsid string comment '基站标识'  
    ,grid_id string comment '网格号'  
    ,biz_type string comment '业务类型'  
    ,event_type string comment '事件类型'  
    ,data_source string comment '数据源'  
) 
comment  '位置数据融合表'
PARTITIONED BY (
    day_id string comment '天分区'  
) 
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' 
STORED AS TEXTFILE
location '/data/tour/dwd/dwd_res_regn_mergelocation_msk_d'; 

// 添加分区
alter table dwd.dwd_res_regn_mergelocation_msk_d add partition(day_id=20180503);
mergeSQL
// hive 直接运行速度太慢,可用手动load/put文件方式

// 手动load
load data local inpath '/usr/local/soft/ctyun/dwd_merge/part-00000*' into table dwd.dwd_res_regn_mergelocation_msk_d partition(day_id=20180503);

// union all
insert into table dwd.dwd_res_regn_mergelocation_msk_d partition(day_id="20180503")
select  mdn  
        ,start_time  
        ,county_id  
        ,longi  
        ,lati  
        ,bsid  
        ,grid_id  
        ,biz_type  
        ,event_type  
        ,data_source 
from ods.ods_oidd
where day_id = "20180503"
union all
select  mdn  
        ,start_time  
        ,county_id  
        ,longi  
        ,lati  
        ,bsid  
        ,grid_id  
        ,biz_type  
        ,event_type  
        ,data_source 
from ods.ods_wcdr
where day_id = "20180503"
union all
select  mdn  
        ,start_time  
        ,county_id  
        ,longi  
        ,lati  
        ,bsid  
        ,grid_id  
        ,biz_type  
        ,event_type  
        ,data_source 
from ods.ods_dpi
where day_id = "20180503"
union all
select  mdn  
        ,start_time  
        ,county_id  
        ,longi  
        ,lati  
        ,bsid  
        ,grid_id  
        ,biz_type  
        ,event_type  
        ,data_source 
from ods.ods_ddr
where day_id = "20180503";
dwm_staypoint_msk_d

计算一个人在一个网格内的停留时间,按手机号,网格id,区县id分组
1、对所有时间进行排序
2、取第一个点的开始时间和最后一个点的结束时间

CREATE EXTERNAL TABLE IF NOT EXISTS dwm.dwm_staypoint_msk_d (
    mdn string comment '用户手机号码'  
    ,longi string comment '网格中心点经度'  
    ,lati string comment '网格中心点纬度'  
    ,grid_id string comment '停留点所在电信内部网格号'  
    ,county_id string comment '停留点区县'  
    ,duration string comment '机主在停留点停留的时间长度(分钟),lTime-eTime'  
    ,grid_first_time string comment '网格第一个记录位置点时间(秒级)'  
    ,grid_last_time string comment '网格最后一个记录位置点时间(秒级)'  
) 
comment  '停留点表'
PARTITIONED BY (
    day_id string comment '天分区'  
) 
ROW FORMAT DELIMITED 
    FIELDS TERMINATED BY '\t' 
STORED AS TEXTFILE
location '/data/tour/dwm/dwm_staypoint_msk_d'; 

通过grid_id 网格id 获取 网格中心点经纬度 longi、lati

SQL
该SQL执行会出现问题: 执行流程一直处于 0% Map  0% reduce
/**
insert OVERWRITE table dwm.dwm_staypoint_msk_d partition(day_id=20180503)
select  t1.mdn
        ,get_points(grid_id)[0] as longi
        ,get_points(grid_id)[1] as lati
        ,t1.grid_id
        ,t1.county_id
        ,dateBetweenUDF(t1.grid_first_time,t1.grid_last_time) as duration
        ,t1.grid_first_time
        ,t1.grid_last_time
from (
    select  mdn
            ,grid_id
            ,county_id
            ,min(split(start_time,',')[0]) as grid_first_time
            ,max(split(start_time,',')[1]) as grid_last_time
    from dwd.dwd_res_regn_mergelocation_msk_d
    where day_id="20180503"
    group by mdn, grid_id, county_id
)t1;
*/

优化后的SQL:

WITH split_table as (
SELECT
mdn
,grid_id
,county_id
,split(start_time,',')[1] as grid_first_time
,split(start_time,',')[0] as grid_last_time
FROM dwd.dwd_res_regn_mergelocation_msk_d
where day_id="20180503"
)
, max_min_table as (
SELECT
mdn
,grid_id
,county_id
,Max(grid_first_time) OVER(PARTITION BY mdn,grid_id,county_id) as grid_first_time
,MIN(grid_last_time) OVER(PARTITION BY mdn,grid_id,county_id) as grid_last_time
FROM split_table 
)

insert OVERWRITE table dwm.dwm_staypoint_msk_d partition(day_id=20180503)
SELECT 
t1.mdn
,get_points(t1.grid_id)[0] as longi
,get_points(t1.grid_id)[1] as lati
,t1.grid_id
,t1.county_id
,dateBetweenUDF(t1.grid_first_time,t1.grid_last_time) as duration
,t1.grid_first_time
,t1.grid_last_time
FROM (
SELECT
mdn
,grid_id
,county_id
,grid_first_time
,grid_last_time
FROM max_min_table
group by 
mdn
,grid_id
,county_id
,grid_first_time
,grid_last_time
) t1

dws_province_tourist_msk_d

游客定义

​ 出行距离大于300km

​ 常住地在 用户画像表 中

​ 在省内停留时间大于3个小时

CREATE EXTERNAL TABLE IF NOT EXISTS dws.dws_province_tourist_msk_d (
    mdn string comment '手机号大写MD5加密'  
    ,source_county_id string comment '游客来源区县'  
    ,d_province_id string comment '旅游目的地省代码'  
    ,d_stay_time double comment '游客在该省停留的时间长度(小时)'  
    ,d_max_distance double comment '游客本次出游距离'  
) 
comment  '旅游应用专题数据省级别-天'
PARTITIONED BY (
    day_id string comment '日分区'  
) 
ROW FORMAT DELIMITED 
    FIELDS TERMINATED BY '\t' 
STORED AS PARQUET
location '/data/tour/dws/dws_province_tourist_msk_d'; 

停留点表dwm_staypoint_msk_d与用户画像维表dim_usertag_msk_m 通过mdn关联,使用get_city_or_prov_id(county_id,“province”)方法,传入county_id,返回province_id,然后按mdn、province_id、resi_county_id分组,使用calLength(grid_id, resi_grid_id) 传入网格id、居住地网格id,算出出行距离,并计算每个用户到每个省的累计出行时间,然后取出 累计时间最大值超过3小时(180分钟),出行距离大于300km的用户

dws_city_tourist_msk_d

出行距离大于100km

在市内停留时间大于3个小时

CREATE EXTERNAL TABLE IF NOT EXISTS dws.dws_city_tourist_msk_d (
    mdn string comment '手机号大写MD5加密'  
    ,source_county_id string comment '游客来源区县'  
    ,d_city_id string comment '旅游目的地市代码'  
    ,d_stay_time double comment '游客在该省市停留的时间长度(小时)'  
    ,d_max_distance double comment '游客本次出游距离'  
) 
comment  '旅游应用专题数据城市级别-天'
PARTITIONED BY (
    day_id string comment '日分区'  
) 
ROW FORMAT DELIMITED 
    FIELDS TERMINATED BY '\t' 
STORED AS PARQUET
location '/data/tour/dws/dws_city_tourist_msk_d'; 

停留点表dwm_staypoint_msk_d与用户画像维表dim_usertag_msk_m 通过mdn关联,使用get_city_or_prov_id(county_id,“city”)方法,传入county_id,返回city_id,然后按mdn、city_id、resi_county_id分组,使用calLength(grid_id, resi_grid_id) 传入网格id、居住地网格id,算出出行距离,并计算每个用户到每个市的累计出行时间,然后取出 累计时间最大值超过3小时(180分钟),出行距离大于100km的用户

dws_county_tourist_msk_d

出行距离大于10km

在县内停留时间大于3个小时

CREATE EXTERNAL TABLE IF NOT EXISTS dws.dws_county_tourist_msk_d (
    mdn string comment '手机号大写MD5加密'  
    ,source_county_id string comment '游客来源区县'  
    ,d_county_id string comment '旅游目的地县代码'  
    ,d_stay_time double comment '游客在该县停留的时间长度(小时)'  
    ,d_max_distance double comment '游客本次出游距离'  
) 
comment  '旅游应用专题数据县级别-天'
PARTITIONED BY (
    day_id string comment '日分区'  
) 
ROW FORMAT DELIMITED 
    FIELDS TERMINATED BY '\t' 
STORED AS PARQUET
location '/data/tour/dws/dws_county_tourist_msk_d'; 

停留点表dwm_staypoint_msk_d与用户画像维表dim_usertag_msk_m 通过mdn关联,按mdn、county_id、resi_county_id分组,使用calLength(grid_id, resi_grid_id) 传入网格id、居住地id,算出出行距离,并计算每个用户到每个县的累计出行时间,然后取出 累计时间最大值超过3小时(180分钟),出行距离大于10km的用户

SQL
insert into table dws.dws_county_tourist_msk_d partition(day_id="20180503")
select  ttt1.mdn
        ,ttt1.source_county_id
        ,ttt1.d_county_id
        ,ttt1.d_stay_time
        ,ttt1.d_max_distance
from(
        select  mdn
                ,resi_county_id as source_county_id
                ,county_id as d_county_id
                ,sum(duration) as d_stay_time
                ,max(calLength(tt1.grid_id,tt1.resi_grid_id)) as d_max_distance
        from(
                select  t1.mdn
                        ,t1.grid_id
                        ,t1.county_id
                        ,t1.duration
                        ,t2.resi_county_id
                        ,t2.resi_grid_id
                from (
                        select  *
                        from dwm.dwm_staypoint_msk_d
                        where day_id='20180503'
                ) t1 join(
                        select *
                        from dim.dim_usertag_msk_m
                        where month_id='201805'
                ) t2 on t1.mdn = t2.mdn
        ) tt1 group by tt1.mdn,tt1.county_id,tt1.resi_county_id
)ttt1 where d_stay_time > 180 and d_max_distance > 10000
;
DIM层
dim_usertag_msk_m
CREATE EXTERNAL TABLE IF NOT EXISTS dim.dim_usertag_msk_m (
    mdn string comment '手机号大写MD5加密'  
    ,name string comment '姓名'  
    ,gender string comment '性别,1男2女'  
    ,age string comment '年龄'  
    ,id_number string comment '证件号码'  
    ,number_attr string comment '号码归属地'  
    ,trmnl_brand string comment '终端品牌'    
    ,trmnl_price string comment '终端价格'
    ,packg string comment '套餐'  
    ,conpot string comment '消费潜力'  
    ,resi_grid_id string comment '常住地网格'  
    ,resi_county_id string comment '常住地区县'  
) 
comment  '用户画像表'
PARTITIONED BY (
    month_id string comment '月分区'  
) 
ROW FORMAT DELIMITED 
    FIELDS TERMINATED BY '\t' 
STORED AS PARQUET
location '/data/tour/dim/dim_usertag_msk_m'; 

// 添加分区
alter table dim.dim_usertag_msk_m add partition(month_id=201805);
// 加载数据
load data local inpath '/usr/local/soft/ctyun/dim_usertag_msk_m/month_id=201805/*' into table dim.dim_usertag_msk_m partition(month_id=201805);
ADS层

根据需求建设

需求矩阵

根据省游客表计算如下指标
  • 客流量按天 [省id,客流量]

  • 性别按天 [省id,性别,客流量]

  • 年龄按天 [省id,年龄,客流量]

  • 常住地按天 [省id,常住地市,客流量]

  • 归属地按天 [省id,归属地市,客流量]

  • 终端型号按天 [省id,终端型号,客流量]

  • 消费等级按天 [省id,消费等级,客流量]

  • 停留时长按天 [省id,停留时长,客流量]

根据市游客表计算如下指标
  • 客流量按天 [市id,客流量]
  • 性别按天 [市id,性别,客流量]
  • 年龄按天 [市id,年龄,客流量]
  • 常住地按天 [市id,常住地市,客流量]
  • 归属地按天 [市id,归属地市,客流量]
  • 终端型号按天 [市id,终端型号,客流量]
  • 消费等级按天 [市id,消费等级,客流量]
  • 停留时长按天 [市id,停留时长,客流量]
根据区县游客表计算如下指标
  • 客流量按天 [区县id,客流量]
select  t1.d_county_id
        ,count(*) as d_county_cnt
from (
    select  d_county_id
    from dws.dws_county_tourist_msk_d
    where day_id="20180503"
)t1 group by t1.d_county_id;
  • 性别按天 [区县id,性别,客流量]
select  t1.d_county_id
        ,t2.gender
        ,count(*) as d_county_gender_cnt
from(
    select  mdn
            ,d_county_id
    from dws.dws_county_tourist_msk_d
    where day_id="20180503"
) t1 left join (
    select  mdn
            ,gender
    from dim.dim_usertag_msk_m
    where month_id=201805
) t2 on t1.mdn = t2.mdn
group by t1.d_county_id,t2.gender;
  • 年龄按天 [区县id,年龄,客流量]
  • 常住地按天 [区县id,常住地市,客流量]
  • 归属地按天 [区县id,归属地市,客流量]
select  t1.d_county_id
        ,t2.number_attr
        ,count(*) as d_county_number_attr_cnt
from(
    select  mdn
            ,d_county_id
    from dws.dws_county_tourist_msk_d
    where day_id="20180503"
) t1 left join (
    select  mdn
            ,number_attr
    from dim.dim_usertag_msk_m
    where month_id=20180503
) t2 on t1.mdn = t2.mdn
group by t1.d_county_id,t2.number_attr;
  • 终端型号按天 [区县id,终端型号,客流量]
  • 消费等级按天 [区县id,消费等级,客流量]
  • 停留时长按天 [区县id,停留时长,客流量]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1492840.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软考63-上午题-【面向对象技术】-面向对象的基本概念2

一、动态绑定、静态绑定 1-1、动态绑定、静态绑定的定义 编译时进行的绑定 静态绑定 运行时进行的绑定 动态绑定 动态绑定&#xff0c;和类的继承和多态想关联的。 在运行过程中&#xff0c;当一个对象发送消息请求服务时&#xff0c;要根据接受对象的具体情况将请求的操作…

gitlab的安装

1、下载rpm 安装包 (1)直接命令下载 wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-11.6.10-ce.0.el7.x86_64.rpm&#xff08;2&#xff09;直接去服务器上下载包 Index of /gitlab-ce/yum/el7/ | 清华大学开源软件镜像站 | Tsinghua Open Source…

html标签之列表标签,含爱奇艺,小米,腾讯,阿里

什么是css块元素&#xff1f; 块级元素是独占一行显示的。它的兄弟元素必定不会与其在同一行中&#xff08;除非脱离了文档流&#xff09;。通俗点来说&#xff0c;就是块元素(block element)一般是其他元素的容器元素&#xff0c;能容纳其他块元素或内联元素。 css块元素的三…

Mol2文件处理-拆分、合并、提取名称、计数与格式转换

欢迎浏览我的CSND博客&#xff01; Blockbuater_drug …点击进入 文章目录 前言一、Mol2文件合并二、Mol2文件拆分为含有单个分子的文件三、Mol2文件分子名称修改与提取3.1 分子名称修改去除空格3.2 文件名称提取 四、Mol2文件包含分子计数4.1 Mol2文件中分子计数4.2 分子计数传…

容器化软件应用简化传统设备的连接

| Docker容器如何简化工业物联网解决方案 制造和包装工厂可通过集成IT和OT技术来改善运营&#xff0c;从而释放预测性维护、数据分析以及接入强大的企业管理应用等优势。然而&#xff0c;对于缺乏员工、时间或资源的企业而言&#xff0c;实施工业物联网解决方案并不容易。对此…

Nircmd集成定时执行专家之后的使用场景

Nircmd工具拥有了定时执行功能之后&#xff0c;可以用于以下场景&#xff1a; 1. 自动化日常工作 定时清理系统垃圾文件定时备份重要文件定时关闭或重启电脑定时发送邮件或短信定时执行其他程序或脚本 2. 监控系统状态 定时检查系统温度定时检查磁盘空间定时检查网络连接定时…

浏览器工作原理与Javascript高级(异步)

总体介绍 浏览器运行是多进程的&#xff0c;包括主进程、渲染进行、网络进程和GPU进程等等 解析HTML时(渲染进程)用到两大引擎&#xff0c;一个是渲染引擎&#xff08;用于渲染页面&#xff09;、一个是JS引擎用于解析JS代码。又JS引擎运行是单线程的&#xff0c;所以渲染和 …

【LeetCode:98. 验证二叉搜索树 + 递归】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

消息队列-kafka-服务端处理架构(架构,Topic文件结构,服务端数据的一致性)

服务端处理架构 资料来源于网络 网络线程池&#xff1a; 接受请求&#xff0c;num.network.threads&#xff0c;默认为 3&#xff0c;专门处理客户的发送的请求。 IO 线程池&#xff1a; num.io.threads&#xff0c;默认为 8&#xff0c;专门处理业务请求。也就是它不负责发…

CSS盒模型居中方法,web开发问题

CSS 篇 link 与 import 的区别 link 是 HTML 方式&#xff0c; import 是CSS方式link 最大限度支持并行下载&#xff0c; import 过多嵌套导致串行下载&#xff0c;出现 FOUC (文档样式短暂失效)link 可以通过 rel"alternate stylesheet" 指定候选样式浏览器对 lin…

数据结构学习(四)高级数据结构

高级数据结构 1. 概念 之所以称它们为高级的数据结构&#xff0c;是因为它们的实现要比那些常用的数据结构要复杂很多&#xff0c;能够让我们在处理复杂问题的过程中&#xff0c; 多拥有一把利器&#xff0c;同时掌握好它们的性质&#xff0c;以及所适应的场合&#xff0c;在…

第十篇:如何利用人工智能技术做好营销流量整形管理?(Traffic Shaping)- 我为什么要翻译介绍美国人工智能科技巨头IAB公司

IAB平台&#xff0c;使命和功能 IAB成立于1996年&#xff0c;总部位于纽约市​​​​​​​。 作为美国的人工智能科技巨头社会媒体和营销专业平台公司&#xff0c;互动广告局&#xff08;IAB- the Interactive Advertising Bureau&#xff09;自1996年成立以来&#xff0c;先…

基于springboot+vue实现食品安全管理系统项目【项目源码+论文说明】

基于springboot实现食品安全管理系统演示 摘要 食品行业同其他行业有很多的差别&#xff0c;食品行业不仅要管食品的生产和销售&#xff0c;还要管食品的库存和保质期&#xff0c;那么对于食品管理者来说&#xff0c;就存在着一定的难度。况且食品的种类复杂&#xff0c;存储条…

ZWT_各向同性线弹性材料本构模型umat的应用

线弹性材料本构模型 对于多数材料而言&#xff0c;在微小变形的假设下&#xff0c;会满足线弹性理论&#xff0c;数学可以表示为&#xff1a; σ i j C i j k l ε k l E 1 ν ( ε i j ν 1 − 2 ν ε k k δ i j ) \begin{align*} \sigma_{ij}&C_{ijkl}\varepsilon…

风丘道路载荷数据采集(RLDA)测试方案

一 背景 整车厂在汽车上市前&#xff0c;了解产品所能承受的载荷是非常重要的&#xff0c;因此需进行道路载荷数据采集&#xff08;RLDA&#xff09;测试。通过获得车辆在实际试验场或公路道路中行驶的载荷信息来为整车台架道路模拟试验提供目标信号输入&#xff0c;以及为用于…

android高级面试题及答案,已拿offer

一、java相关 java基础 1、java 中和 equals 和 hashCode 的区别 2、int、char、long 各占多少字节数 3、int 与 integer 的区别 4、谈谈对 java 多态的理解 5、String、StringBuffer、StringBuilder 区别 6、什么是内部类&#xff1f;内部类的作用 7、抽象类和接口区别 java高…

无人机生态环境监测、图像处理与GIS数据分析

构建“天空地”一体化监测体系是新形势下生态、环境、水文、农业、林业、气象等资源环境领域的重大需求&#xff0c;无人机生态环境监测在一体化监测体系中扮演着极其重要的角色。通过无人机航空遥感技术可以实现对地表空间要素的立体观测&#xff0c;获取丰富多样的地理空间数…

将ppt里的视频导出来

将ppt的后缀从pptx改为zip 找到【media】里面有存放图片和音频以及视频&#xff0c;看文件名后缀可以找到&#xff0c;mp4的即为视频&#xff0c;直接复制粘贴到桌面即可。 关闭压缩软件把ppt后缀改回&#xff0c;不影响ppt正常使用。

【Redis】Redis持久化模式RDB

目录 引子 RDB RDB的优缺点 小节一下 引子 不论把Redis作为数据库还是缓存来使用&#xff0c;他肯定有数据需要持久化&#xff0c;这里我们就来聊聊两种持久化机制。这两种机制&#xff0c;其实是 快照 与 日志 的形式。快照:就是当前数据的备份&#xff0c;我可以拷贝到磁…

Docker入门——安装部署(openEuler)、镜像加速

安装 1&#xff09;依赖的基础环境 64 位CPU Linux kernel(内核) 3.10 Linux kernel cgroups and namespaces 我用的是openEuler&#xff0c;所以直接yum安装(推荐&#xff0c;因为二进制安装&#xff0c;docker命令中补全操作要另外安装软件) [rootlocalhost ~]# yum -y…