系统业务数据仓库

第1章 电商业务与数据结构简介
1.1 电商业务流程

1.2 电商常识(SKU、SPU)
SKU=Stock Keeping Unit(库存量基本单位)。现在已经被引申为产品统一编号的简称,每种产品均对应有唯一的SKU号。
SPU(Standard Product Unit):是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息集合。
比如,咱们购买一台iPhoneX手机,iPhoneX手机就是一个SPU,但是你购买的时候,不可能是以iPhoneX手机为单位买的,商家也不可能以iPhoneX为单位记录库存SKU。必须要以什么颜色什么版本的iPhoneX为单位。比如,你购买的是一台银色、128G内存的、支持联通网络的iPhoneX,商家也会以这个单位来记录库存数。那这个更细致的单位就叫库存单元(SKU)。
那SPU又是干什么的呢?

SPU表示一类商品。好处就是:可以共用商品图片,海报、销售属性等。
1.3 电商表结构

1.3.1 订单表(order_info)
标签 含义
id 订单编号
total_amount 订单金额
order_status 订单状态
user_id 用户id
payment_way 支付方式
out_trade_no 支付流水号
create_time 创建时间
operate_time 操作时间
1.3.2 订单详情表(order_detail)
标签 含义
id 订单编号
order_id 订单号
user_id 用户id
sku_id 商品id
sku_name 商品名称
order_price 商品价格
sku_num 商品数量
create_time 创建时间
1.3.3 商品表
标签 含义
id skuId
spu_id spuid
price 价格
sku_name 商品名称
sku_desc 商品描述
weight 重量
tm_id 品牌id
category3_id 品类id
create_time 创建时间
1.3.4 用户表
标签 含义
id 用户id
name 姓名
birthday 生日
gender 性别
email 邮箱
user_level 用户等级
create_time 创建时间
1.3.5 商品一级分类表
标签 含义
id id
name 名称
1.3.6 商品二级分类表
标签 含义
id id
name 名称
category1_id 一级品类id
1.3.7 商品三级分类表
标签 含义
id id
name 名称
Category2_id 二级品类id
1.3.8 支付流水表
标签 含义
id 编号
out_trade_no 对外业务编号
order_id 订单编号
user_id 用户编号
alipay_trade_no 支付宝交易流水编号
total_amount 支付金额
subject 交易内容
payment_type 支付类型
payment_time 支付时间
第2章 数仓理论(面试重点)
2.1 表的分类
2.1.1 实体表
实体表,一般是指一个现实存在的业务对象,比如用户,商品,商家,销售员等等。
用户表:
用户id 姓名 生日 性别 邮箱 用户等级 创建时间
1 张三 2011-11-11 男 [email protected] 2 2018-11-11
2 李四 2011-11-11 女 [email protected] 3 2018-11-11
3 王五 2011-11-11 中性 [email protected] 1 2018-11-11
… … … … … … …
2.1.2 维度表
维度表,一般是指对应一些业务状态,编号的解释表。也可以称之为码表。
比如地区表,订单状态,支付方式,审批状态,商品分类等等。
订单状态表:
订单状态编号 订单状态名称
1 未支付
2 支付
3 发货中
4 已发货
5 已完成
商品分类表:
商品分类编号 分类名称
1 服装
2 保健
3 电器
4 图书
2.1.3 事务型事实表
事务型事实表,一般指随着业务发生不断产生的数据。特点是一旦发生不会再变化。
一般比如,交易流水,操作日志,出库入库记录等等。
交易流水表:
编号 对外业务编号 订单编号 用户编号 支付宝交易流水编号 支付金额 交易内容 支付类型 支付时间
1 7577697945 1 111 QEyF-63000323 223.00 海狗人参丸1 alipay 2019-02-10 00:50:02
2 0170099522 2 222 qdwV-25111279 589.00 海狗人参丸2 wechatpay 2019-02-10 00:50:02
3 1840931679 3 666 hSUS-65716585 485.00 海狗人参丸3 unionpay 2019-02-10 00:50:02
。。。 。。。 。。。 。。。 。。。 。。。 。。。 。。。 。。。
2.1.4 周期型事实表
周期型事实表,一般指随着业务发生不断产生的数据。
与事务型不同的是,数据会随着业务周期性的推进而变化。
比如订单,其中订单状态会周期性变化。再比如,请假、贷款申请,随着批复状态在周期性变化。
订单表:
订单编号 订单金额 订单状态 用户id 支付方式 支付流水号 创建时间 操作时间
1 223.00 2 111 alipay QEyF-63000323 2019-02-10 00:01:29 2019-02-10 00:01:29
2 589.00 2 222 wechatpay qdwV-25111279 2019-02-10 00:05:02 2019-02-10 00:05:02
3 485.00 1 666 unionpay hSUS-65716585 2019-02-10 00:50:02 2019-02-10 00:50:02
。。。 。。。 。。。 。。。 。。。 。。。 。。。 。。。
2.2 同步策略
数据同步策略的类型包括:全量表、增量表、新增及变化表、拉链表
全量表:存储完整的数据。
增量表:存储新增加的数据。
新增及变化表:存储新增加的数据和变化的数据。
拉链表:对新增及变化表做定期合并。
2.2.1 实体表同步策略
实体表:比如用户,商品,商家,销售员等
实体表数据量比较小:通常可以做每日全量,就是每天存一份完整数据。即每日全量。
2.2.2 维度表同步策略
维度表:比如订单状态,审批状态,商品分类
维度表数据量比较小:通常可以做每日全量,就是每天存一份完整数据。即每日全量。
说明:
1)针对可能会有变化的状态数据可以存储每日全量。
2)没变化的客观世界的维度(比如性别,地区,民族,政治成分,鞋子尺码)可以只存一份固定值。
2.2.3 事务型事实表同步策略
事务型事实表:比如,交易流水,操作日志,出库入库记录等。
因为数据不会变化,而且数据量巨大,所以每天只同步新增数据即可,所以可以做成每日增量表,即每日创建一个分区存储。
2.2.4 周期型事实表同步策略
周期型事实表:比如,订单、请假、贷款申请等
这类表从数据量的角度,存每日全量的话,数据量太大,冗余也太大。如果用每日增量的话无法反应数据变化。
每日新增及变化量,包括了当日的新增和修改。一般来说这个表,足够计算大部分当日数据的。但是这种依然无法解决能够得到某一个历史时间点(时间切片)的切片数据。
所以要用利用每日新增和变化表,制作一张拉链表,以方便的取到某个时间切片的快照数据。所以我们需要得到每日新增及变化量。
拉链表:
name姓名 start新名字创建时间 end名字更改时间
张三 1990/1/1 2018/12/31
张小三 2019/1/1 2019/4/30
张大三 2019/5/1 9999-99-99
。。。 。。。 。。。
select * from user where start =<’2019-1-2’ and end>=’2019-1-2’
2.3 范式理论
2.3.1 范式概念
关系型数据库设计时,遵照一定的规范要求,目的在于降低数据的冗余性,目前业界范式有:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)、第五范式(5NF)。
范式可以理解为一张数据表的表结构,符合的设计标准的级别。
使用范式的根本目的是:
1)减少数据冗余,尽量让每个数据只出现一次。
2)保证数据一致性
缺点是获取数据时,需要通过Join拼接出最后的数据。
2.3.2 函数依赖

2.3.3 三范式区分

2.4 关系建模与维度建模
关系模型

关系模型主要应用与OLTP系统中,为了保证数据的一致性以及避免冗余,所以大部分业务系统的表都是遵循第三范式的。
维度模型

维度模型主要应用于OLAP系统中,因为关系模型虽然冗余少,但是在大规模数据,跨表分析统计查询过程中,会造成多表关联,这会大大降低执行效率。
所以把相关各种表整理成两种:事实表和维度表两种。所有维度表围绕着事实表进行解释。
2.5 雪花模型、星型模型和星座模型
在维度建模的基础上又分为三种模型:星型模型、雪花模型、星座模型。

第3章 数仓搭建
3.0 配置Hadoop支持Snappy压缩
1)将编译后支持Snappy压缩的Hadoop jar包解压缩,并将lib/native目录中所有文件上传到hadoop102的/opt/module/hadoop-2.7.2/lib/native目录,并分发到hadoop103 hadoop104。
2)重新启动Hadoop。
3)检查支持的压缩方式
[atguigu@hadoop102 native]$ hadoop checknative
hadoop: true /opt/module/hadoop-2.7.2/lib/native/libhadoop.so
zlib: true /lib64/libz.so.1
snappy: true /opt/module/hadoop-2.7.2/lib/native/libsnappy.so.1
lz4: true revision:99
bzip2: false
3.1 业务数据生成
3.1.1 建表语句
1)通过SQLyog创建数据库gmall

2)设置数据库编码

3)导入建表语句(1建表脚本)

选择->1建表脚本.sql

4)重复步骤3的导入方式,依次导入:2商品分类数据插入脚本、3函数脚本、4存储过程脚本。
3.1.2 生成业务数据
1)生成业务数据函数说明
init_data ( do_date_string VARCHAR(20) , order_incr_num INT, user_incr_num INT , sku_num INT , if_truncate BOOLEAN ):
参数一:do_date_string生成数据日期
参数二:order_incr_num订单id个数
参数三:user_incr_num用户id个数
参数四:sku_num商品sku个数
参数五:if_truncate是否删除数据
2)案例测试:
(1)需求:生成日期2019年2月10日数据、订单1000个、用户200个、商品sku300个、删除原始数据。

CALL init_data(‘2019-02-10’,1000,200,300,TRUE);
(2)查询生成数据结果
SELECT * from base_category1;
SELECT * from base_category2;
SELECT * from base_category3;

SELECT * from order_info;
SELECT * from order_detail;

SELECT * from sku_info;
SELECT * from user_info;

SELECT * from payment_info;
3.2 业务数据导入数仓

3.2.1 Sqoop安装
详见尚硅谷大数据技术之Sqoop

3.2.2 Sqoop导入命令
/opt/module/sqoop/bin/sqoop import
–connect
–username
–password
–target-dir
–delete-target-dir
–num-mappers
–fields-terminated-by
–query “$2” ’ and $CONDITIONS;’
3.2.3 分析表

3.2.4 Sqoop定时导入脚本
1)在/home/atguigu/bin目录下创建脚本sqoop_import.sh
[atguigu@hadoop102 bin]$ vim sqoop_import.sh
在脚本中填写如下内容
#!/bin/bash

db_date=$2
echo $db_date
db_name=gmall

import_data() {
/opt/module/sqoop/bin/sqoop import
–connect jdbc:mysql://hadoop102:3306/KaTeX parse error: Undefined control sequence: \ at position 9: db_name \̲ ̲--username root…db_name/db/ 1 / 1/ 1/db_date
–delete-target-dir
–num-mappers 1
–fields-terminated-by “\t”
–query “$2”’ and $CONDITIONS;’
}

import_sku_info(){
import_data “sku_info” “select
id, spu_id, price, sku_name, sku_desc, weight, tm_id,
category3_id, create_time
from sku_info where 1=1”
}

import_user_info(){
import_data “user_info” “select
id, name, birthday, gender, email, user_level,
create_time
from user_info where 1=1”
}

import_base_category1(){
import_data “base_category1” “select
id, name from base_category1 where 1=1”
}

import_base_category2(){
import_data “base_category2” “select
id, name, category1_id from base_category2 where 1=1”
}

import_base_category3(){
import_data “base_category3” “select id, name, category2_id from base_category3 where 1=1”
}

import_order_detail(){
import_data “order_detail” “select
od.id,
order_id,
user_id,
sku_id,
sku_name,
order_price,
sku_num,
o.create_time
from order_info o, order_detail od
where o.id=od.order_id
and DATE_FORMAT(create_time,’%Y-%m-%d’)=’$db_date’”
}

import_payment_info(){
import_data “payment_info” “select
id,
out_trade_no,
order_id,
user_id,
alipay_trade_no,
total_amount,
subject,
payment_type,
payment_time
from payment_info
where DATE_FORMAT(payment_time,’%Y-%m-%d’)=’$db_date’”
}

import_order_info(){
import_data “order_info” “select
id,
total_amount,
order_status,
user_id,
payment_way,
out_trade_no,
create_time,
operate_time
from order_info
where (DATE_FORMAT(create_time,’%Y-%m-%d’)=‘ d b d a t e ′ o r D A T E F O R M A T ( o p e r a t e t i m e , ′ db_date' or DATE_FORMAT(operate_time,'%Y-%m-%d')=' dbdateorDATEFORMAT(operatetime,db_date’)”
}

case 1 i n " b a s e c a t e g o r y 1 " ) i m p o r t b a s e c a t e g o r y 1 ; ; " b a s e c a t e g o r y 2 " ) i m p o r t b a s e c a t e g o r y 2 ; ; " b a s e c a t e g o r y 3 " ) i m p o r t b a s e c a t e g o r y 3 ; ; " o r d e r i n f o " ) i m p o r t o r d e r i n f o ; ; " o r d e r d e t a i l " ) i m p o r t o r d e r d e t a i l ; ; " s k u i n f o " ) i m p o r t s k u i n f o ; ; " u s e r i n f o " ) i m p o r t u s e r i n f o ; ; " p a y m e n t i n f o " ) i m p o r t p a y m e n t i n f o ; ; " a l l " ) i m p o r t b a s e c a t e g o r y 1 i m p o r t b a s e c a t e g o r y 2 i m p o r t b a s e c a t e g o r y 3 i m p o r t o r d e r i n f o i m p o r t o r d e r d e t a i l i m p o r t s k u i n f o i m p o r t u s e r i n f o i m p o r t p a y m e n t i n f o ; ; e s a c 2 ) 增 加 脚 本 执 行 权 限 [ a t g u i g u @ h a d o o p 102 b i n ] 1 in "base_category1") import_base_category1 ;; "base_category2") import_base_category2 ;; "base_category3") import_base_category3 ;; "order_info") import_order_info ;; "order_detail") import_order_detail ;; "sku_info") import_sku_info ;; "user_info") import_user_info ;; "payment_info") import_payment_info ;; "all") import_base_category1 import_base_category2 import_base_category3 import_order_info import_order_detail import_sku_info import_user_info import_payment_info ;; esac 2)增加脚本执行权限 [atguigu@hadoop102 bin] 1in"basecategory1")importbasecategory1;;"basecategory2")importbasecategory2;;"basecategory3")importbasecategory3;;"orderinfo")importorderinfo;;"orderdetail")importorderdetail;;"skuinfo")importskuinfo;;"userinfo")importuserinfo;;"paymentinfo")importpaymentinfo;;"all")importbasecategory1importbasecategory2importbasecategory3importorderinfoimportorderdetailimportskuinfoimportuserinfoimportpaymentinfo;;esac2[atguigu@hadoop102bin] chmod 777 sqoop_import.sh
3)执行脚本导入数据
[atguigu@hadoop102 bin]$ sqoop_import.sh all 2019-02-10
4)在SQLyog中生成2019年2月11日数据
CALL init_data(‘2019-02-11’,1000,200,300,TRUE);
5)执行脚本导入数据
[atguigu@hadoop102 bin]$ sqoop_import.sh all 2019-02-11
3.2.5 Sqoop导入数据异常处理
1)问题描述:执行Sqoop导入数据脚本时,发生如下异常
java.sql.SQLException: Streaming result set com.mysql.jdbc.RowDataDynamic@65d6b83b is still active. No statements may be issued when any streaming result sets are open and in use on a given connection. Ensure that you have called .close() on any active streaming result sets before attempting more queries.
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:930)
at com.mysql.jdbc.MysqlIO.checkForOutstandingStreamingData(MysqlIO.java:2646)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1861)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2101)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2548)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2477)
at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1422)
at com.mysql.jdbc.ConnectionImpl.getMaxBytesPerChar(ConnectionImpl.java:2945)
at com.mysql.jdbc.Field.getMaxBytesPerCharacter(Field.java:582)
2)问题解决方案:增加如下导入参数
–driver com.mysql.jdbc.Driver
3.3 ODS层
完全仿照业务数据库中的表字段,一模一样的创建ODS层对应表。
3.3.1 创建订单表
hive (gmall)>
drop table if exists ods_order_info;
create external table ods_order_info (
id string COMMENT ‘订单编号’,
total_amount decimal(10,2) COMMENT ‘订单金额’,
order_status string COMMENT ‘订单状态’,
user_id string COMMENT ‘用户id’,
payment_way string COMMENT ‘支付方式’,
out_trade_no string COMMENT ‘支付流水号’,
create_time string COMMENT ‘创建时间’,
operate_time string COMMENT ‘操作时间’
) COMMENT ‘订单表’
PARTITIONED BY (dt string)
row format delimited fields terminated by ‘\t’
location ‘/warehouse/gmall/ods/ods_order_info/’
;
3.3.2 创建订单详情表
hive (gmall)>
drop table if exists ods_order_detail;
create external table ods_order_detail(
id string COMMENT ‘订单编号’,
order_id string COMMENT ‘订单号’,
user_id string COMMENT ‘用户id’,
sku_id string COMMENT ‘商品id’,
sku_name string COMMENT ‘商品名称’,
order_price string COMMENT ‘商品价格’,
sku_num string COMMENT ‘商品数量’,
create_time string COMMENT ‘创建时间’
) COMMENT ‘订单明细表’
PARTITIONED BY (dt string)
row format delimited fields terminated by ‘\t’
location ‘/warehouse/gmall/ods/ods_order_detail/’
;
3.3.3 创建商品表
hive (gmall)>
drop table if exists ods_sku_info;
create external table ods_sku_info(
id string COMMENT ‘skuId’,
spu_id string COMMENT ‘spuid’,
price decimal(10,2) COMMENT ‘价格’,
sku_name string COMMENT ‘商品名称’,
sku_desc string COMMENT ‘商品描述’,
weight string COMMENT ‘重量’,
tm_id string COMMENT ‘品牌id’,
category3_id string COMMENT ‘品类id’,
create_time string COMMENT ‘创建时间’
) COMMENT ‘商品表’
PARTITIONED BY (dt string)
row format delimited fields terminated by ‘\t’
location ‘/warehouse/gmall/ods/ods_sku_info/’
;
3.3.4 创建用户表
hive (gmall)>
drop table if exists ods_user_info;
create external table ods_user_info(
id string COMMENT ‘用户id’,
name string COMMENT ‘姓名’,
birthday string COMMENT ‘生日’,
gender string COMMENT ‘性别’,
email string COMMENT ‘邮箱’,
user_level string COMMENT ‘用户等级’,
create_time string COMMENT ‘创建时间’
) COMMENT ‘用户信息’
PARTITIONED BY (dt string)
row format delimited fields terminated by ‘\t’
location ‘/warehouse/gmall/ods/ods_user_info/’
;
3.3.5 创建商品一级分类表
hive (gmall)>
drop table if exists ods_base_category1;
create external table ods_base_category1(
id string COMMENT ‘id’,
name string COMMENT ‘名称’
) COMMENT ‘商品一级分类’
PARTITIONED BY (dt string)
row format delimited fields terminated by ‘\t’
location ‘/warehouse/gmall/ods/ods_base_category1/’
;
3.3.6 创建商品二级分类表
hive (gmall)>
drop table if exists ods_base_category2;
create external table ods_base_category2(
id string COMMENT ’ id’,
name string COMMENT ‘名称’,
category1_id string COMMENT ‘一级品类id’
) COMMENT ‘商品二级分类’
PARTITIONED BY (dt string)
row format delimited fields terminated by ‘\t’
location ‘/warehouse/gmall/ods/ods_base_category2/’
;
3.3.7 创建商品三级分类表
hive (gmall)>
drop table if exists ods_base_category3;
create external table ods_base_category3(
id string COMMENT ’ id’,
name string COMMENT ‘名称’,
category2_id string COMMENT ‘二级品类id’
) COMMENT ‘商品三级分类’
PARTITIONED BY (dt string)
row format delimited fields terminated by ‘\t’
location ‘/warehouse/gmall/ods/ods_base_category3/’
;
3.3.8 创建支付流水表
hive (gmall)>
drop table if exists ods_payment_info;
create external table ods_payment_info(
id bigint COMMENT ‘编号’,
out_trade_no string COMMENT ‘对外业务编号’,
order_id string COMMENT ‘订单编号’,
user_id string COMMENT ‘用户编号’,
alipay_trade_no string COMMENT ‘支付宝交易流水编号’,
total_amount decimal(16,2) COMMENT ‘支付金额’,
subject string COMMENT ‘交易内容’,
payment_type string COMMENT ‘支付类型’,
payment_time string COMMENT ‘支付时间’
) COMMENT ‘支付流水表’
PARTITIONED BY (dt string)
row format delimited fields terminated by ‘\t’
location ‘/warehouse/gmall/ods/ods_payment_info/’
;
3.3.9 ODS层数据导入脚本
1)在/home/atguigu/bin目录下创建脚本ods_db.sh
[atguigu@hadoop102 bin]$ vim ods_db.sh
在脚本中填写如下内容
#!/bin/bash

APP=gmall
hive=/opt/module/hive/bin/hive

如果是输入的日期按照取输入日期;如果没输入日期取当前时间的前一天

if [ -n “$1” ] ;then
do_date=$1
else
do_date=date -d "-1 day" +%F
fi

sql="
load data inpath ‘/origin_data/ A P P / d b / o r d e r i n f o / APP/db/order_info/ APP/db/orderinfo/do_date’ OVERWRITE into table " A P P " . o d s o r d e r i n f o p a r t i t i o n ( d t = ′ APP".ods_order_info partition(dt=' APP".odsorderinfopartition(dt=do_date’);

load data inpath ‘/origin_data/ A P P / d b / o r d e r d e t a i l / APP/db/order_detail/ APP/db/orderdetail/do_date’ OVERWRITE into table " A P P " . o d s o r d e r d e t a i l p a r t i t i o n ( d t = ′ APP".ods_order_detail partition(dt=' APP".odsorderdetailpartition(dt=do_date’);

load data inpath ‘/origin_data/ A P P / d b / s k u i n f o / APP/db/sku_info/ APP/db/skuinfo/do_date’ OVERWRITE into table " A P P " . o d s s k u i n f o p a r t i t i o n ( d t = ′ APP".ods_sku_info partition(dt=' APP".odsskuinfopartition(dt=do_date’);

load data inpath ‘/origin_data/ A P P / d b / u s e r i n f o / APP/db/user_info/ APP/db/userinfo/do_date’ OVERWRITE into table " A P P " . o d s u s e r i n f o p a r t i t i o n ( d t = ′ APP".ods_user_info partition(dt=' APP".odsuserinfopartition(dt=do_date’);

load data inpath ‘/origin_data/ A P P / d b / p a y m e n t i n f o / APP/db/payment_info/ APP/db/paymentinfo/do_date’ OVERWRITE into table " A P P " . o d s p a y m e n t i n f o p a r t i t i o n ( d t = ′ APP".ods_payment_info partition(dt=' APP".odspaymentinfopartition(dt=do_date’);

load data inpath ‘/origin_data/ A P P / d b / b a s e c a t e g o r y 1 / APP/db/base_category1/ APP/db/basecategory1/do_date’ OVERWRITE into table " A P P " . o d s b a s e c a t e g o r y 1 p a r t i t i o n ( d t = ′ APP".ods_base_category1 partition(dt=' APP".odsbasecategory1partition(dt=do_date’);

load data inpath ‘/origin_data/ A P P / d b / b a s e c a t e g o r y 2 / APP/db/base_category2/ APP/db/basecategory2/do_date’ OVERWRITE into table " A P P " . o d s b a s e c a t e g o r y 2 p a r t i t i o n ( d t = ′ APP".ods_base_category2 partition(dt=' APP".odsbasecategory2partition(dt=do_date’);

load data inpath ‘/origin_data/ A P P / d b / b a s e c a t e g o r y 3 / APP/db/base_category3/ APP/db/basecategory3/do_date’ OVERWRITE into table “ A P P " . o d s b a s e c a t e g o r y 3 p a r t i t i o n ( d t = ′ APP".ods_base_category3 partition(dt=' APP".odsbasecategory3partition(dt=do_date’);
"
h i v e − e " hive -e " hivee"sql”
2)增加脚本执行权限
[atguigu@hadoop102 bin]$ chmod 777 ods_db.sh
3)执行脚本导入数据
[atguigu@hadoop102 bin]$ ods_db.sh 2019-02-10
[atguigu@hadoop102 bin]$ ods_db.sh 2019-02-11
4)查询导入数据
hive (gmall)>
select * from ods_order_info where dt=‘2019-02-10’ limit 1;
select * from ods_order_info where dt=‘2019-02-11’ limit 1;
3.4 DWD层
对ODS层数据进行判空过滤。对商品分类表进行维度退化(降维)。
3.4.1 创建订单表
hive (gmall)>
drop table if exists dwd_order_info;
create external table dwd_order_info (
id string COMMENT ‘’,
total_amount decimal(10,2) COMMENT ‘’,
order_status string COMMENT ’ 1 2 3 4 5’,
user_id string COMMENT ‘id’,
payment_way string COMMENT ‘’,
out_trade_no string COMMENT ‘’,
create_time string COMMENT ‘’,
operate_time string COMMENT ‘’
)
PARTITIONED BY (dt string)
stored as parquet
location ‘/warehouse/gmall/dwd/dwd_order_info/’
tblproperties (“parquet.compression”=“snappy”)
;
3.4.2 创建订单详情表
hive (gmall)>
drop table if exists dwd_order_detail;
create external table dwd_order_detail(
id string COMMENT ‘’,
order_id decimal(10,2) COMMENT ‘’,
user_id string COMMENT ‘id’,
sku_id string COMMENT ‘id’,
sku_name string COMMENT ‘’,
order_price string COMMENT ‘’,
sku_num string COMMENT ‘’,
create_time string COMMENT ‘’
)
PARTITIONED BY (dt string)
stored as parquet
location ‘/warehouse/gmall/dwd/dwd_order_detail/’
tblproperties (“parquet.compression”=“snappy”)
;
3.4.3 创建用户表
hive (gmall)>
drop table if exists dwd_user_info;
create external table dwd_user_info(
id string COMMENT ‘id’,
name string COMMENT ‘’,
birthday string COMMENT ‘’,
gender string COMMENT ‘’,
email string COMMENT ‘’,
user_level string COMMENT ‘’,
create_time string COMMENT ‘’
)
PARTITIONED BY (dt string)
stored as parquet
location ‘/warehouse/gmall/dwd/dwd_user_info/’
tblproperties (“parquet.compression”=“snappy”)
;
3.4.4 创建支付流水表
hive (gmall)>
drop table if exists dwd_payment_info;
create external table dwd_payment_info(
id bigint COMMENT ‘’,
out_trade_no string COMMENT ‘’,
order_id string COMMENT ‘’,
user_id string COMMENT ‘’,
alipay_trade_no string COMMENT ‘’,
total_amount decimal(16,2) COMMENT ‘’,
subject string COMMENT ‘’,
payment_type string COMMENT ‘’,
payment_time string COMMENT ‘’
)
PARTITIONED BY (dt string)
stored as parquet
location ‘/warehouse/gmall/dwd/dwd_payment_info/’
tblproperties (“parquet.compression”=“snappy”)
;
3.4.5 创建商品表(增加分类)

hive (gmall)>
drop table if exists dwd_sku_info;
create external table dwd_sku_info(
id string COMMENT ‘skuId’,
spu_id string COMMENT ‘spuid’,
price decimal(10,2) COMMENT ‘’,
sku_name string COMMENT ‘’,
sku_desc string COMMENT ‘’,
weight string COMMENT ‘’,
tm_id string COMMENT ‘id’,
category3_id string COMMENT ‘1id’,
category2_id string COMMENT ‘2id’,
category1_id string COMMENT ‘3id’,
category3_name string COMMENT ‘3’,
category2_name string COMMENT ‘2’,
category1_name string COMMENT ‘1’,
create_time string COMMENT ‘’
)
PARTITIONED BY (dt string)
stored as parquet
location ‘/warehouse/gmall/dwd/dwd_sku_info/’
tblproperties (“parquet.compression”=“snappy”)
;
3.4.6 DWD层数据导入脚本
1)在/home/atguigu/bin目录下创建脚本dwd_db.sh
[atguigu@hadoop102 bin]$ vim dwd_db.sh
在脚本中填写如下内容
#!/bin/bash

定义变量方便修改

APP=gmall
hive=/opt/module/hive/bin/hive

如果是输入的日期按照取输入日期;如果没输入日期取当前时间的前一天

if [ -n “$1” ] ;then
do_date=$1
else
do_date=date -d "-1 day" +%F
fi

sql="

set hive.exec.dynamic.partition.mode=nonstrict;

insert overwrite table “ A P P " . d w d o r d e r i n f o p a r t i t i o n ( d t ) s e l e c t ∗ f r o m " APP".dwd_order_info partition(dt) select * from " APP".dwdorderinfopartition(dt)selectfrom"APP”.ods_order_info
where dt=’$do_date’ and id is not null;

insert overwrite table “ A P P " . d w d o r d e r d e t a i l p a r t i t i o n ( d t ) s e l e c t ∗ f r o m " APP".dwd_order_detail partition(dt) select * from " APP".dwdorderdetailpartition(dt)selectfrom"APP”.ods_order_detail
where dt=’$do_date’ and id is not null;

insert overwrite table “ A P P " . d w d u s e r i n f o p a r t i t i o n ( d t ) s e l e c t ∗ f r o m " APP".dwd_user_info partition(dt) select * from " APP".dwduserinfopartition(dt)selectfrom"APP”.ods_user_info
where dt=’$do_date’ and id is not null;

insert overwrite table “ A P P " . d w d p a y m e n t i n f o p a r t i t i o n ( d t ) s e l e c t ∗ f r o m " APP".dwd_payment_info partition(dt) select * from " APP".dwdpaymentinfopartition(dt)selectfrom"APP”.ods_payment_info
where dt=’$do_date’ and id is not null;

insert overwrite table “ A P P " . d w d s k u i n f o p a r t i t i o n ( d t ) s e l e c t s k u . i d , s k u . s p u i d , s k u . p r i c e , s k u . s k u n a m e , s k u . s k u d e s c , s k u . w e i g h t , s k u . t m i d , s k u . c a t e g o r y 3 i d , c 2. i d c a t e g o r y 2 i d , c 1. i d c a t e g o r y 1 i d , c 3. n a m e c a t e g o r y 3 n a m e , c 2. n a m e c a t e g o r y 2 n a m e , c 1. n a m e c a t e g o r y 1 n a m e , s k u . c r e a t e t i m e , s k u . d t f r o m " APP".dwd_sku_info partition(dt) select sku.id, sku.spu_id, sku.price, sku.sku_name, sku.sku_desc, sku.weight, sku.tm_id, sku.category3_id, c2.id category2_id, c1.id category1_id, c3.name category3_name, c2.name category2_name, c1.name category1_name, sku.create_time, sku.dt from " APP".dwdskuinfopartition(dt)selectsku.id,sku.spuid,sku.price,sku.skuname,sku.skudesc,sku.weight,sku.tmid,sku.category3id,c2.idcategory2id,c1.idcategory1id,c3.namecategory3name,c2.namecategory2name,c1.namecategory1name,sku.createtime,sku.dtfrom"APP”.ods_sku_info sku
join “ A P P " . o d s b a s e c a t e g o r y 3 c 3 o n s k u . c a t e g o r y 3 i d = c 3. i d j o i n " APP".ods_base_category3 c3 on sku.category3_id=c3.id join " APP".odsbasecategory3c3onsku.category3id=c3.idjoin"APP”.ods_base_category2 c2 on c3.category2_id=c2.id
join " A P P " . o d s b a s e c a t e g o r y 1 c 1 o n c 2. c a t e g o r y 1 i d = c 1. i d w h e r e s k u . d t = ′ APP".ods_base_category1 c1 on c2.category1_id=c1.id where sku.dt=' APP".odsbasecategory1c1onc2.category1id=c1.idwheresku.dt=do_date’ and c2.dt=‘ d o d a t e ′ a n d c 3. d t = ′ do_date' and c3.dt=' dodateandc3.dt=do_date’ and c1.dt=’$do_date’
and sku.id is not null;
"

h i v e − e " hive -e " hivee"sql"
2)增加脚本执行权限
[atguigu@hadoop102 bin]$ chmod 777 dwd_db.sh
3)执行脚本导入数据
[atguigu@hadoop102 bin]$ dwd_db.sh 2019-02-10
[atguigu@hadoop102 bin]$ dwd_db.sh 2019-02-11
4)查看导入数据
hive (gmall)>
select * from dwd_sku_info where dt=‘2019-02-10’ limit 2;
select * from dwd_sku_info where dt=‘2019-02-11’ limit 2;
3.4.3 小结
思考:
1)维度退化要付出什么代价?
如果被退化的维度,还有其他业务表使用,退化后处理起来就麻烦些。
2)想想在实际业务中还有那些维度表可以退化
城市的三级分类(省、市、县)等
3.5 DWS层之用户行为宽表
1)为什么要建宽表
需求目标,把每个用户单日的行为聚合起来组成一张多列宽表,以便之后关联用户维度信息后进行,不同角度的统计分析。

3.5.1 创建用户行为宽表
hive (gmall)>
drop table if exists dws_user_action;
create external table dws_user_action
(
user_id string comment ‘用户 id’,
order_count bigint comment '下单次数 ',
order_amount decimal(16,2) comment '下单金额 ',
payment_count bigint comment ‘支付次数’,
payment_amount decimal(16,2) comment '支付金额 ',
comment_count bigint comment ‘评论次数’
) COMMENT ‘每日用户行为宽表’
PARTITIONED BY (dt string)
stored as parquet
location ‘/warehouse/gmall/dws/dws_user_action/’
tblproperties (“parquet.compression”=“snappy”);
3.5.2 向用户行为宽表导入数据
1)导入数据
hive (gmall)>
with
tmp_order as
(
select
user_id,
count() order_count,
sum(oi.total_amount) order_amount
from dwd_order_info oi
where date_format(oi.create_time,‘yyyy-MM-dd’)=‘2019-02-10’
group by user_id
) ,
tmp_payment as
(
select
user_id,
sum(pi.total_amount) payment_amount,
count(
) payment_count
from dwd_payment_info pi
where date_format(pi.payment_time,‘yyyy-MM-dd’)=‘2019-02-10’
group by user_id
),
tmp_comment as
(
select
user_id,
count(*) comment_count
from dwd_comment_log c
where date_format(c.dt,‘yyyy-MM-dd’)=‘2019-02-10’
group by user_id
)

insert overwrite table dws_user_action partition(dt=‘2019-02-10’)
select
user_actions.user_id,
sum(user_actions.order_count),
sum(user_actions.order_amount),
sum(user_actions.payment_count),
sum(user_actions.payment_amount),
sum(user_actions.comment_count)
from
(
select
user_id,
order_count,
order_amount,
0 payment_count,
0 payment_amount,
0 comment_count
from tmp_order

union all
select
    user_id,
    0,
    0,
    payment_count,
    payment_amount,
    0
from tmp_payment

union all
select
    user_id,
    0,
    0,
    0,
    0,
    comment_count
from tmp_comment

) user_actions
group by user_id;
2)查询导入结果
hive (gmall)> select * from dws_user_action;
3.5.3 用户行为数据宽表导入脚本
1)在/home/atguigu/bin目录下创建脚本dws_db_wide.sh
[atguigu@hadoop102 bin]$ vim dws_db_wide.sh
在脚本中填写如下内容
#!/bin/bash

定义变量方便修改

APP=gmall
hive=/opt/module/hive/bin/hive

如果是输入的日期按照取输入日期;如果没输入日期取当前时间的前一天

if [ -n “$1” ] ;then
do_date=$1
else
do_date=date -d "-1 day" +%F
fi

sql="

with
tmp_order as
(
select
user_id,
sum(oi.total_amount) order_amount,
count() order_count
from " A P P " . d w d o r d e r i n f o o i w h e r e d a t e f o r m a t ( o i . c r e a t e t i m e , ′ y y y y − M M − d d ′ ) = ′ APP".dwd_order_info oi where date_format(oi.create_time,'yyyy-MM-dd')=' APP".dwdorderinfooiwheredateformat(oi.createtime,yyyyMMdd)=do_date’
group by user_id
) ,
tmp_payment as
(
select
user_id,
sum(pi.total_amount) payment_amount,
count(
) payment_count
from " A P P " . d w d p a y m e n t i n f o p i w h e r e d a t e f o r m a t ( p i . p a y m e n t t i m e , ′ y y y y − M M − d d ′ ) = ′ APP".dwd_payment_info pi where date_format(pi.payment_time,'yyyy-MM-dd')=' APP".dwdpaymentinfopiwheredateformat(pi.paymenttime,yyyyMMdd)=do_date’
group by user_id
),
tmp_comment as
(
select
user_id,
count(*) comment_count
from " A P P " . d w d c o m m e n t l o g c w h e r e d a t e f o r m a t ( c . d t , ′ y y y y − M M − d d ′ ) = ′ APP".dwd_comment_log c where date_format(c.dt,'yyyy-MM-dd')=' APP".dwdcommentlogcwheredateformat(c.dt,yyyyMMdd)=do_date’
group by user_id
)

Insert overwrite table " A P P " . d w s u s e r a c t i o n p a r t i t i o n ( d t = ′ APP".dws_user_action partition(dt=' APP".dwsuseractionpartition(dt=do_date’)
select
user_actions.user_id,
sum(user_actions.order_count),
sum(user_actions.order_amount),
sum(user_actions.payment_count),
sum(user_actions.payment_amount),
sum(user_actions.comment_count)
from
(
select
user_id,
order_count,
order_amount,
0 payment_count,
0 payment_amount,
0 comment_count
from tmp_order

union all
select
    user_id,
    0,
    0,
    payment_count,
    payment_amount,
    0
from tmp_payment

union all
select
    user_id,
    0,
    0,
    0,
    0,
    comment_count 
from tmp_comment

) user_actions
group by user_id;
"

h i v e − e " hive -e " hivee"sql"
2)增加脚本执行权限
[atguigu@hadoop102 bin]$ chmod 777 dws_db_wide.sh
3)执行脚本导入数据
[atguigu@hadoop102 bin]$ dws_db_wide.sh 2019-02-11
4)查看导入数据
hive (gmall)>
select * from dws_user_action where dt=‘2019-02-11’ limit 2;
第4章 需求一:GMV成交总额
4.1 ADS层
4.1.1 什么是GMV

4.1.2 建表语句
hive (gmall)>
drop table if exists ads_gmv_sum_day;
create external table ads_gmv_sum_day(
dt string COMMENT ‘统计日期’,
gmv_count bigint COMMENT ‘当日gmv订单个数’,
gmv_amount decimal(16,2) COMMENT ‘当日gmv订单总金额’,
gmv_payment decimal(16,2) COMMENT ‘当日支付金额’
) COMMENT ‘GMV’
row format delimited fields terminated by ‘\t’
location ‘/warehouse/gmall/ads/ads_gmv_sum_day/’
;

4.1.3 数据导入
1)数据导入
hive (gmall)>
insert into table ads_gmv_sum_day
select
‘2019-02-10’ dt,
sum(order_count) gmv_count,
sum(order_amount) gmv_amount,
sum(payment_amount) payment_amount
from dws_user_action
where dt =‘2019-02-10’
group by dt
;
2)查询导入数据
hive (gmall)> select * from ads_gmv_sum_day;
4.1.4 数据导入脚本
1)在/home/atguigu/bin目录下创建脚本ads_db_gmv.sh
[atguigu@hadoop102 bin]$ vim ads_db_gmv.sh
在脚本中填写如下内容
#!/bin/bash

定义变量方便修改

APP=gmall
hive=/opt/module/hive/bin/hive

如果是输入的日期按照取输入日期;如果没输入日期取当前时间的前一天

if [ -n “$1” ] ;then
do_date=$1
else
do_date=date -d "-1 day" +%F
fi

sql="
insert into table " A P P " . a d s g m v s u m d a y s e l e c t ′ APP".ads_gmv_sum_day select ' APP".adsgmvsumdayselectdo_date’ dt,
sum(order_count) gmv_count,
sum(order_amount) gmv_amount,
sum(payment_amount) payment_amount
from " A P P " . d w s u s e r a c t i o n w h e r e d t = ′ APP".dws_user_action where dt =' APP".dwsuseractionwheredt=do_date’
group by dt;
"

h i v e − e " hive -e " hivee"sql"
2)增加脚本执行权限
[atguigu@hadoop102 bin]$ chmod 777 ads_db_gmv.sh
3)执行脚本导入数据
[atguigu@hadoop102 bin]$ ads_db_gmv.sh 2019-02-11
4)查看导入数据
hive (gmall)>
select * from ads_gmv_sum_day where dt=‘2019-02-11’ limit 2;
第5章 需求二:转化率及漏斗分析
5.1 什么是转化率

5.2 ADS层之新增用户占日活跃用户比率

5.2.1 建表语句
hive (gmall)>
drop table if exists ads_user_convert_day;
create external table ads_user_convert_day(
dt string COMMENT ‘统计日期’,
uv_m_count bigint COMMENT ‘当日活跃设备’,
new_m_count bigint COMMENT ‘当日新增设备’,
new_m_ratio decimal(10,2) COMMENT ‘当日新增占日活的比率’
) COMMENT ‘转化率’
row format delimited fields terminated by ‘\t’
location ‘/warehouse/gmall/ads/ads_user_convert_day/’
;
5.2.2 数据导入
1)数据导入
hive (gmall)>
insert into table ads_user_convert_day
select
‘2019-02-10’,
sum(uc.dc) sum_dc,
sum(uc.nmc) sum_nmc,
cast(sum( uc.nmc)/sum( uc.dc)*100 as decimal(10,2)) new_m_ratio
from
(
select
day_count dc,
0 nmc
from ads_uv_count
where dt=‘2019-02-10’

union all
select
    0 dc,
    new_mid_count nmc
from ads_new_mid_count
where create_date='2019-02-10'

)uc;
2)查看导入数据
hive (gmall)>
select * from ads_user_convert_day;
5.3 ADS层之用户行为漏斗分析

5.3.1 建表语句
hive (gmall)>
drop table if exists ads_user_action_convert_day;
create external table ads_user_action_convert_day(
dt string COMMENT ‘统计日期’,
total_visitor_m_count bigint COMMENT ‘总访问人数’,
order_u_count bigint COMMENT ‘下单人数’,
visitor2order_convert_ratio decimal(10,2) COMMENT ‘访问到下单转化率’,
payment_u_count bigint COMMENT ‘支付人数’,
order2payment_convert_ratio decimal(10,2) COMMENT ‘下单到支付的转化率’
) COMMENT ‘用户行为漏斗分析’
row format delimited fields terminated by ‘\t’
location ‘/warehouse/gmall/ads/ads_user_action_convert_day/’
;
5.3.2 数据导入
1)数据导入
hive (gmall)>
insert into table ads_user_action_convert_day
select
‘2019-02-10’,
uv.day_count,
ua.order_count,
cast(ua.order_count/uv.day_count as decimal(10,2)) visitor2order_convert_ratio,
ua.payment_count,
cast(ua.payment_count/ua.order_count as decimal(10,2)) order2payment_convert_ratio
from
(
select
dt,
sum(if(order_count>0,1,0)) order_count,
sum(if(payment_count>0,1,0)) payment_count
from dws_user_action
where dt=‘2019-02-10’
group by dt
)ua join ads_uv_count uv on uv.dt=ua.dt
;
2)查询导入数据
hive (gmall)> select * from ads_user_action_convert_day;
第6章 需求三:品牌复购率
需求:以月为单位统计,购买2次以上商品的用户
6.1 复购率计算分析

6.2 DWS层
6.2.1 用户购买商品明细表(宽表)

hive (gmall)>
drop table if exists dws_sale_detail_daycount;
create external table dws_sale_detail_daycount
(
user_id string comment ‘用户 id’,
sku_id string comment ‘商品 Id’,
user_gender string comment ‘用户性别’,
user_age string comment ‘用户年龄’,
user_level string comment ‘用户等级’,
order_price decimal(10,2) comment ‘商品价格’,
sku_name string comment ‘商品名称’,
sku_tm_id string comment ‘品牌id’,
sku_category3_id string comment ‘商品三级品类id’,
sku_category2_id string comment ‘商品二级品类id’,
sku_category1_id string comment ‘商品一级品类id’,
sku_category3_name string comment ‘商品三级品类名称’,
sku_category2_name string comment ‘商品二级品类名称’,
sku_category1_name string comment ‘商品一级品类名称’,
spu_id string comment ‘商品 spu’,
sku_num int comment ‘购买个数’,
order_count string comment ‘当日下单单数’,
order_amount string comment ‘当日下单金额’
) COMMENT ‘用户购买商品明细表’
PARTITIONED BY (dt string)
stored as parquet
location ‘/warehouse/gmall/dws/dws_user_sale_detail_daycount/’
tblproperties (“parquet.compression”=“snappy”);
6.2.2 数据导入
hive (gmall)>
with
tmp_detail as
(
select
user_id,
sku_id,
sum(sku_num) sku_num,
count() order_count,
sum(od.order_price
sku_num) order_amount
from dwd_order_detail od
where od.dt=‘2019-02-10’
group by user_id, sku_id
)
insert overwrite table dws_sale_detail_daycount partition(dt=‘2019-02-10’)
select
tmp_detail.user_id,
tmp_detail.sku_id,
u.gender,
months_between(‘2019-02-10’, u.birthday)/12 age,
u.user_level,
price,
sku_name,
tm_id,
category3_id,
category2_id,
category1_id,
category3_name,
category2_name,
category1_name,
spu_id,
tmp_detail.sku_num,
tmp_detail.order_count,
tmp_detail.order_amount
from tmp_detail
left join dwd_user_info u on tmp_detail.user_id =u.id and u.dt=‘2019-02-10’
left join dwd_sku_info s on tmp_detail.sku_id =s.id and s.dt=‘2019-02-10’
;
6.2.3 数据导入脚本
1)在/home/atguigu/bin目录下创建脚本dws_sale.sh
[atguigu@hadoop102 bin]$ vim dws_sale.sh
在脚本中填写如下内容
#!/bin/bash

定义变量方便修改

APP=gmall
hive=/opt/module/hive/bin/hive

如果是输入的日期按照取输入日期;如果没输入日期取当前时间的前一天

if [ -n “$1” ] ;then
do_date=$1
else
do_date=date -d "-1 day" +%F
fi

sql="

set hive.exec.dynamic.partition.mode=nonstrict;

with
tmp_detail as
(
select
user_id,
sku_id,
sum(sku_num) sku_num,
count() order_count,
sum(od.order_price
sku_num) order_amount
from “ A P P " . d w d o r d e r d e t a i l o d w h e r e o d . d t = ′ APP".dwd_order_detail od where od.dt=' APP".dwdorderdetailodwhereod.dt=do_date’
group by user_id, sku_id
)
insert overwrite table “ A P P " . d w s s a l e d e t a i l d a y c o u n t p a r t i t i o n ( d t = ′ APP".dws_sale_detail_daycount partition(dt=' APP".dwssaledetaildaycountpartition(dt=do_date’)
select
tmp_detail.user_id,
tmp_detail.sku_id,
u.gender,
months_between(' d o d a t e ′ , u . b i r t h d a y ) / 12 a g e , u . u s e r l e v e l , p r i c e , s k u n a m e , t m i d , c a t e g o r y 3 i d , c a t e g o r y 2 i d , c a t e g o r y 1 i d , c a t e g o r y 3 n a m e , c a t e g o r y 2 n a m e , c a t e g o r y 1 n a m e , s p u i d , t m p d e t a i l . s k u n u m , t m p d e t a i l . o r d e r c o u n t , t m p d e t a i l . o r d e r a m o u n t f r o m t m p d e t a i l l e f t j o i n " do_date', u.birthday)/12 age, u.user_level, price, sku_name, tm_id, category3_id, category2_id, category1_id, category3_name, category2_name, category1_name, spu_id, tmp_detail.sku_num, tmp_detail.order_count, tmp_detail.order_amount from tmp_detail left join " dodate,u.birthday)/12age,u.userlevel,price,skuname,tmid,category3id,category2id,category1id,category3name,category2name,category1name,spuid,tmpdetail.skunum,tmpdetail.ordercount,tmpdetail.orderamountfromtmpdetailleftjoin"APP”.dwd_user_info u
on tmp_detail.user_id=u.id and u.dt=' d o d a t e ′ l e f t j o i n " do_date' left join " dodateleftjoin"APP”.dwd_sku_info s on tmp_detail.sku_id =s.id and s.dt=’$do_date’;

"
h i v e − e " hive -e " hivee"sql"
2)增加脚本执行权限
[atguigu@hadoop102 bin]$ chmod 777 dws_sale.sh
3)执行脚本导入数据
[atguigu@hadoop102 bin]$ dws_sale.sh 2019-02-11
4)查看导入数据
hive (gmall)>
select * from dws_sale_detail_daycount where dt=‘2019-02-11’ limit 2;
6.3 ADS层品牌复购率

6.3.1 建表语句
hive (gmall)>
drop table ads_sale_tm_category1_stat_mn;
create external table ads_sale_tm_category1_stat_mn
(
tm_id string comment ‘品牌id’,
category1_id string comment '1级品类id ',
category1_name string comment '1级品类名称 ',
buycount bigint comment ‘购买人数’,
buy_twice_last bigint comment ‘两次以上购买人数’,
buy_twice_last_ratio decimal(10,2) comment ‘单次复购率’,
buy_3times_last bigint comment ‘三次以上购买人数’,
buy_3times_last_ratio decimal(10,2) comment ‘多次复购率’,
stat_mn string comment ‘统计月份’,
stat_date string comment ‘统计日期’
) COMMENT ‘复购率统计’
row format delimited fields terminated by ‘\t’
location ‘/warehouse/gmall/ads/ads_sale_tm_category1_stat_mn/’
;
6.3.2 数据导入
1)数据导入
hive (gmall)>
insert into table ads_sale_tm_category1_stat_mn
select
mn.sku_tm_id,
mn.sku_category1_id,
mn.sku_category1_name,
sum(if(mn.order_count>=1,1,0)) buycount,
sum(if(mn.order_count>=2,1,0)) buyTwiceLast,
sum(if(mn.order_count>=2,1,0))/sum( if(mn.order_count>=1,1,0)) buyTwiceLastRatio,
sum(if(mn.order_count>=3,1,0)) buy3timeLast ,
sum(if(mn.order_count>=3,1,0))/sum( if(mn.order_count>=1,1,0)) buy3timeLastRatio ,
date_format(‘2019-02-10’ ,‘yyyy-MM’) stat_mn,
‘2019-02-10’ stat_date
from
(
select
user_id,
sd.sku_tm_id,
sd.sku_category1_id,
sd.sku_category1_name,
sum(order_count) order_count
from dws_sale_detail_daycount sd
where date_format(dt,‘yyyy-MM’)=date_format(‘2019-02-10’ ,‘yyyy-MM’)
group by user_id, sd.sku_tm_id, sd.sku_category1_id, sd.sku_category1_name
) mn
group by mn.sku_tm_id, mn.sku_category1_id, mn.sku_category1_name
;
2)查询导入数据
hive (gmall)> select * from ads_sale_tm_category1_stat_mn;
6.3.3 数据导入脚本
1)在/home/atguigu/bin目录下创建脚本ads_sale.sh
[atguigu@hadoop102 bin]$ vim ads_sale.sh
在脚本中填写如下内容
#!/bin/bash

定义变量方便修改

APP=gmall
hive=/opt/module/hive/bin/hive

如果是输入的日期按照取输入日期;如果没输入日期取当前时间的前一天

if [ -n “$1” ] ;then
do_date=$1
else
do_date=date -d "-1 day" +%F
fi

sql="

set hive.exec.dynamic.partition.mode=nonstrict;

insert into table “ A P P " . a d s s a l e t m c a t e g o r y 1 s t a t m n s e l e c t m n . s k u t m i d , m n . s k u c a t e g o r y 1 i d , m n . s k u c a t e g o r y 1 n a m e , s u m ( i f ( m n . o r d e r c o u n t > = 1 , 1 , 0 ) ) b u y c o u n t , s u m ( i f ( m n . o r d e r c o u n t > = 2 , 1 , 0 ) ) b u y T w i c e L a s t , s u m ( i f ( m n . o r d e r c o u n t > = 2 , 1 , 0 ) ) / s u m ( i f ( m n . o r d e r c o u n t > = 1 , 1 , 0 ) ) b u y T w i c e L a s t R a t i o , s u m ( i f ( m n . o r d e r c o u n t > = 3 , 1 , 0 ) ) b u y 3 t i m e L a s t , s u m ( i f ( m n . o r d e r c o u n t > = 3 , 1 , 0 ) ) / s u m ( i f ( m n . o r d e r c o u n t > = 1 , 1 , 0 ) ) b u y 3 t i m e L a s t R a t i o , d a t e f o r m a t ( ′ APP".ads_sale_tm_category1_stat_mn select mn.sku_tm_id, mn.sku_category1_id, mn.sku_category1_name, sum(if(mn.order_count>=1,1,0)) buycount, sum(if(mn.order_count>=2,1,0)) buyTwiceLast, sum(if(mn.order_count>=2,1,0))/sum( if(mn.order_count>=1,1,0)) buyTwiceLastRatio, sum(if(mn.order_count>=3,1,0)) buy3timeLast, sum(if(mn.order_count>=3,1,0))/sum( if(mn.order_count>=1,1,0)) buy3timeLastRatio , date_format(' APP".adssaletmcategory1statmnselectmn.skutmid,mn.skucategory1id,mn.skucategory1name,sum(if(mn.ordercount>=1,1,0))buycount,sum(if(mn.ordercount>=2,1,0))buyTwiceLast,sum(if(mn.ordercount>=2,1,0))/sum(if(mn.ordercount>=1,1,0))buyTwiceLastRatio,sum(if(mn.ordercount>=3,1,0))buy3timeLast,sum(if(mn.ordercount>=3,1,0))/sum(if(mn.ordercount>=1,1,0))buy3timeLastRatio,dateformat(do_date’ ,‘yyyy-MM’) stat_mn,
' d o d a t e ′ s t a t d a t e f r o m ( s e l e c t u s e r i d , o d . s k u t m i d , o d . s k u c a t e g o r y 1 i d , o d . s k u c a t e g o r y 1 n a m e , s u m ( o r d e r c o u n t ) o r d e r c o u n t f r o m " do_date' stat_date from ( select user_id, od.sku_tm_id, od.sku_category1_id, od.sku_category1_name, sum(order_count) order_count from " dodatestatdatefrom(selectuserid,od.skutmid,od.skucategory1id,od.skucategory1name,sum(ordercount)ordercountfrom"APP”.dws_sale_detail_daycount od
where date_format(dt,‘yyyy-MM’)=date_format(’$do_date’ ,‘yyyy-MM’)
group by user_id, od.sku_tm_id, od.sku_category1_id, od.sku_category1_name
) mn
group by mn.sku_tm_id, mn.sku_category1_id, mn.sku_category1_name;

"
h i v e − e " hive -e " hivee"sql"
2)增加脚本执行权限
[atguigu@hadoop102 bin]$ chmod 777 ads_sale.sh
3)执行脚本导入数据
[atguigu@hadoop102 bin]$ ads_sale.sh 2019-02-11
4)查看导入数据
hive (gmall)>
select * from ads_sale_tm_category1_stat_mn limit 2;
6.4 练习:求每个等级的用户对应的复购率前十的商品排行
1)每个等级,每种商品,买一次的用户数,买两次的用户数=》得出复购率
2)利用开窗函数,取每个等级的前十
3)形成脚本
第7章 数据可视化
7.1 在MySQL中创建表
7.1.1 每日活跃统计

1)在MySQL中创建ads_uv_count表
DROP TABLE IF EXISTS ads_uv_count;
CREATE TABLE ads_uv_count (
dt varchar(255) DEFAULT NULL COMMENT ‘统计日期’,
day_count bigint(200) DEFAULT NULL COMMENT ‘当日用户数量’,
wk_count bigint(200) DEFAULT NULL COMMENT ‘当周用户数量’,
mn_count bigint(200) DEFAULT NULL COMMENT ‘当月用户数量’,
is_weekend varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT ‘Y,N是否是周末,用于得到本周最终结果’,
is_monthend varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT ‘Y,N是否是月末,用于得到本月最终结果’
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ‘每日活跃用户数量’ ROW_FORMAT = Dynamic;
2)向MySQL中插入如下数据
INSERT INTO ads_uv_count VALUES (‘2019-03-01 14:10:04’, 20, 30, 100, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-02 14:12:48’, 35, 50, 100, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-03 14:14:07’, 25, 640, 3300, ‘Y’, ‘Y’);
INSERT INTO ads_uv_count VALUES (‘2019-03-04 14:14:14’, 10, 23, 123, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-05 14:14:21’, 80, 121, 131, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-06 14:14:38’, 30, 53, 453, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-07 14:33:27’, 20, 31, 453, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-08 14:33:39’, 10, 53, 453, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-09 14:33:47’, 10, 34, 453, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-10 14:33:54’, 10, 653, 8453, ‘Y’, ‘Y’);
INSERT INTO ads_uv_count VALUES (‘2019-03-11 14:34:04’, 100, 453, 1453, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-12 14:34:10’, 101, 153, 134, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-13 14:34:16’, 100, 286, 313, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-14 14:34:22’, 100, 45, 453, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-15 14:34:29’, 100, 345, 3453, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-16 14:34:35’, 101, 453, 453, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-17 14:34:41’, 100, 678, 9812, ‘Y’, ‘Y’);
INSERT INTO ads_uv_count VALUES (‘2019-03-18 14:34:46’, 100, 186, 193, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-19 14:34:53’, 453, 686, 712, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-20 14:34:57’, 452, 786, 823, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-21 14:35:02’, 214, 58, 213, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-22 14:35:08’, 76, 78, 95, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-23 14:35:13’, 76, 658, 745, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-24 14:35:19’, 76, 687, 9300, ‘Y’, ‘Y’);
INSERT INTO ads_uv_count VALUES (‘2019-03-25 14:35:25’, 76, 876, 923, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-26 14:35:30’, 76, 456, 511, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-27 14:35:35’, 76, 456, 623, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-28 14:35:41’, 43, 753, 4000, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-29 14:35:47’, 76, 876, 4545, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-30 14:35:57’, 76, 354, 523, ‘N’, ‘N’);
INSERT INTO ads_uv_count VALUES (‘2019-03-31 14:36:02’, 43, 634, 6213, ‘Y’, ‘Y’);
7.1.2 留存率统计
1)在MySQL中创建ads_user_retention_day_rate表
DROP TABLE IF EXISTS ads_user_retention_day_rate;
CREATE TABLE ads_user_retention_day_rate (
stat_date varchar(255) DEFAULT NULL COMMENT ‘统计日期’,
create_date varchar(255) DEFAULT NULL COMMENT ‘设备新增日期’,
retention_day bigint(200) DEFAULT NULL COMMENT ‘截止当前日期留存天数’,
retention_count bigint(200) DEFAULT NULL COMMENT ‘留存数量’,
new_mid_count bigint(200) DEFAULT NULL COMMENT ‘当日设备新增数量’,
retention_ratio decimal(10, 2) DEFAULT NULL COMMENT ‘留存率’
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ‘每日用户留存情况’ ROW_FORMAT = Dynamic;
2)向MySQL中插入数据
INSERT INTO ads_user_retention_day_rate VALUES (‘2019-03-09’,‘2019-03-08’, 1,88, 99, 0.78);
INSERT INTO ads_user_retention_day_rate VALUES (‘2019-03-10’,‘2019-03-08’, 2,77, 88, 0.68);
INSERT INTO ads_user_retention_day_rate VALUES (‘2019-03-11’,‘2019-03-08’, 3,66, 77, 0.58);
INSERT INTO ads_user_retention_day_rate VALUES (‘2019-03-12’,‘2019-03-08’, 4,55, 66, 0.48);
INSERT INTO ads_user_retention_day_rate VALUES (‘2019-03-13’,‘2019-03-08’, 5,44, 55, 0.38);
INSERT INTO ads_user_retention_day_rate VALUES (‘2019-03-14’,‘2019-03-08’, 6,33, 44, 0.28);
INSERT INTO ads_user_retention_day_rate VALUES (‘2019-03-10’,‘2019-03-09’, 1,77, 88, 0.56);
INSERT INTO ads_user_retention_day_rate VALUES (‘2019-03-11’,‘2019-03-09’, 2,66, 77, 0.46);
INSERT INTO ads_user_retention_day_rate VALUES (‘2019-03-12’,‘2019-03-09’, 3,55, 66, 0.36);
INSERT INTO ads_user_retention_day_rate VALUES (‘2019-03-13’,‘2019-03-09’, 4,44, 55, 0.26);
INSERT INTO ads_user_retention_day_rate VALUES (‘2019-03-14’,‘2019-03-09’, 5,33, 44, 0.16);
INSERT INTO ads_user_retention_day_rate VALUES (‘2019-03-11’,‘2019-03-10’, 1,66, 77, 0.55);
INSERT INTO ads_user_retention_day_rate VALUES (‘2019-03-12’,‘2019-03-10’, 2,55, 66, 0.45);
INSERT INTO ads_user_retention_day_rate VALUES (‘2019-03-13’,‘2019-03-10’, 3,44, 55, 0.35);
INSERT INTO ads_user_retention_day_rate VALUES (‘2019-03-14’,‘2019-03-10’, 4,33, 44, 0.25);
7.1.3 漏斗分析

1)在MySQL中创建ads_user_action_convert_day表
DROP TABLE IF EXISTS ads_user_action_convert_day;
CREATE TABLE ads_user_action_convert_day (
dt varchar(200) DEFAULT NULL COMMENT ‘统计日期’,
total_visitor_m_count bigint(20) DEFAULT NULL COMMENT ‘总访问人数’,
order_u_count bigint(20) DEFAULT NULL COMMENT ‘下单人数’,
visitor2order_convert_ratio decimal(10, 2) DEFAULT NULL COMMENT ‘购物车到下单转化率’,
payment_u_count bigint(20) DEFAULT NULL COMMENT ‘支付人数’,
order2payment_convert_ratio decimal(10, 2) DEFAULT NULL COMMENT ‘下单到支付的转化率’
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ‘每日用户行为转化率统计’ ROW_FORMAT = Dynamic;
2)向MySQL中插入数据
INSERT INTO ads_user_action_convert_day VALUES (‘2019-04-28 19:36:18’, 10000, 3000, 0.25, 2000, 0.15);
7.1.4 GMV统计

1)在MySQL中创建ads_gmv_sum_day表
DROP TABLE IF EXISTS ads_gmv_sum_day;
CREATE TABLE ads_gmv_sum_day(
dt varchar(200) DEFAULT NULL COMMENT ‘统计日期’,
gmv_count bigint(20) DEFAULT NULL COMMENT ‘当日gmv订单个数’,
gmv_amount decimal(16, 2) DEFAULT NULL COMMENT ‘当日gmv订单总金额’,
gmv_payment decimal(16, 2) DEFAULT NULL COMMENT ‘当日支付金额’
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ‘每日活跃用户数量’ ROW_FORMAT = Dynamic;
2)向MySQL中插入数据
INSERT INTO ads_gmv_sum_day VALUES (‘2019-03-01 22:51:37’, 1000, 210000.00, 2000.00);
INSERT INTO ads_gmv_sum_day VALUES (‘2019-05-08 22:52:32’, 3434, 12413.00, 1.00);
INSERT INTO ads_gmv_sum_day VALUES (‘2019-07-13 22:52:51’, 1222, 324345.00, 1.00);
INSERT INTO ads_gmv_sum_day VALUES (‘2019-09-13 22:53:08’, 2344, 12312.00, 1.00);
7.1.5 全国商品销售

1)在MySQL中创建ads_gmv_sum_province表
DROP TABLE IF EXISTS ads_gmv_sum_province;
CREATE TABLE ads_gmv_sum_province (
province varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
gmv bigint(255) DEFAULT NULL,
remark varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
2)向MySQL中插入数据
INSERT INTO ads_gmv_sum_province VALUES (‘北京’, 2000, ‘’);
INSERT INTO ads_gmv_sum_province VALUES (‘辽宁’, 30000, ‘沈阳:21.1%,大连:20%,鞍山:35%’);
INSERT INTO ads_gmv_sum_province VALUES (‘浙江’, 8002, ‘杭州:20%,舟山:50%’);
7.2 WEB页面查看
1)运行spring-boot-echarts-master程序
2)在web页面上查看显示结果
http://localhost:8080/active
7.3 Sqoop导出脚本
1)编写Sqoop导出脚本
在/home/atguigu/bin目录下创建脚本sqoop_export.sh
[atguigu@hadoop102 bin]$ vim sqoop_export.sh
在脚本中填写如下内容
#!/bin/bash

db_name=gmall

export_data() {
/opt/module/sqoop/bin/sqoop export
–connect “jdbc:mysql://hadoop102:3306/${db_name}?useUnicode=true&characterEncoding=utf-8”
–username root
–password 000000
–table KaTeX parse error: Undefined control sequence: \ at position 3: 1 \̲ ̲--num-mappers 1…db_name/ads/$1
–input-fields-terminated-by “\t”
–update-mode allowinsert
–update-key “tm_id,category1_id,stat_mn,stat_date”
–input-null-string ‘\N’
–input-null-non-string ‘\N’
}

case KaTeX parse error: Unexpected character: '' at position 350: …ate还是insert的问题 ̲--update-mode: … chmod 777 sqoop_export.sh
[atguigu@hadoop102 bin]$ sqoop_export.sh all
4)在MySQL中查看结果
SELECT * FROM ads_uv_count;
SELECT * FROM ads_user_retention_day_rate;
SELECT * FROM ads_user_action_convert_day;
SELECT * FROM ads_gmv_sum_day;
SELECT * FROM ads_gmv_sum_province;
第8章 Azkaban调度器
8.1 Azkaban安装
详见:尚硅谷大数据技术之Azkaban

8.2 GMV指标获取的全调度流程
1)生成数据
CALL init_data(‘2019-02-12’,300,200,300,FALSE);
2)编写Azkaban程序运行job
(1)import.job文件
type=command
do_date=${dt}
command=/home/atguigu/bin/sqoop_import.sh all d o d a t e ( 2 ) o d s . j o b 文 件 t y p e = c o m m a n d d o d a t e = {do_date} (2)ods.job文件 type=command do_date= dodate2ods.jobtype=commanddodate={dt}
dependencies=import
command=/home/atguigu/bin/ods_db.sh d o d a t e ( 3 ) d w d . j o b 文 件 t y p e = c o m m a n d d o d a t e = {do_date} (3)dwd.job文件 type=command do_date= dodate3dwd.jobtype=commanddodate={dt}
dependencies=ods
command=/home/atguigu/bin/dwd_db.sh d o d a t e ( 4 ) d w s . j o b 文 件 t y p e = c o m m a n d d o d a t e = {do_date} (4)dws.job文件 type=command do_date= dodate4dws.jobtype=commanddodate={dt}
dependencies=dwd
command=/home/atguigu/bin/dws_db_wide.sh d o d a t e ( 5 ) a d s . j o b 文 件 t y p e = c o m m a n d d o d a t e = {do_date} (5)ads.job文件 type=command do_date= dodate5ads.jobtype=commanddodate={dt}
dependencies=dws
command=/home/atguigu/bin/ads_db_gmv.sh ${do_date}
(6)export.job文件
type=command
dependencies=ads
command=/home/atguigu/bin/sqoop_export.sh ads_gmv_sum_day
(7)将以上6个文件压缩成gmv-job.zip文件
3)创建Azkaban工程,并上传gmv-job.zip文件。

4)在浏览器中输入https://hadoop102:8443,并在页面上创建工程执行gmv-job.zip任务。
5)等待大约20分钟,在MySQL中查看结果
select * from ads_gmv_sum_day;
第9章 订单表拉链表
9.1 什么是拉链表

9.2 为什么要做拉链表

9.3 拉链表形成过程

9.4 拉链表制作过程图

9.5 拉链表制作过程
9.5.1 步骤0:初始化拉链表(首次独立执行)

1)生成10条原始订单数据
CALL init_data(‘2019-02-13’,10,5,10,TRUE);

[atguigu@hadoop102 bin]$ sqoop_import.sh all 2019-02-13

[atguigu@hadoop102 bin]$ ods_db.sh 2019-02-13

[atguigu@hadoop102 bin]$ dwd_db.sh 2019-02-13
2)建立拉链表
hive (gmall)>
drop table if exists dwd_order_info_his;
create external table dwd_order_info_his(
id string COMMENT ‘订单编号’,
total_amount decimal(10,2) COMMENT ‘订单金额’,
order_status string COMMENT ‘订单状态’,
user_id string COMMENT ‘用户id’ ,
payment_way string COMMENT ‘支付方式’,
out_trade_no string COMMENT ‘支付流水号’,
create_time string COMMENT ‘创建时间’,
operate_time string COMMENT ‘操作时间’,
start_date string COMMENT ‘有效开始日期’,
end_date string COMMENT ‘有效结束日期’
) COMMENT ‘订单拉链表’
stored as parquet
location ‘/warehouse/gmall/dwd/dwd_order_info_his/’
tblproperties (“parquet.compression”=“snappy”);
3)初始化拉链表
hive (gmall)>
insert overwrite table dwd_order_info_his
select
id,
total_amount,
order_status,
user_id,
payment_way,
out_trade_no,
create_time,
operate_time,
‘2019-02-13’,
‘9999-99-99’
from ods_order_info oi
where oi.dt=‘2019-02-13’;
4)查询拉链表中数据
hive (gmall)> select * from dwd_order_info_his limit 2;
9.5.2 步骤1:制作当日变动数据(包括新增,修改)每日执行
1)如何获得每日变动表
(1)最好表内有创建时间和变动时间(Lucky!)
(2)如果没有,可以利用第三方工具监控比如canal,监控MySQL的实时变化进行记录(麻烦)。
(3)逐行对比前后两天的数据, 检查md5(concat(全部有可能变化的字段))是否相同(low)
(4)要求业务数据库提供变动流水(人品,颜值)
2)因为dwd_order_info本身导入过来就是新增变动明细的表,所以不用处理
(1)2019-02-14日新增2条订单数据
CALL init_data(‘2019-02-14’,2,5,10,TRUE);
(2)通过Sqoop把2019-02-14日所有数据导入
sqoop_import.sh all 2019-02-14
(3)ODS层数据导入
ods_db.sh 2019-02-14
(4)DWD层数据导入
dwd_db.sh 2019-02-14
9.5.3 步骤2:先合并变动信息,再追加新增信息,插入到临时表中
1)建立临时表
hive (gmall)>
drop table if exists dwd_order_info_his_tmp;
create table dwd_order_info_his_tmp(
id string COMMENT ‘订单编号’,
total_amount decimal(10,2) COMMENT ‘订单金额’,
order_status string COMMENT ‘订单状态’,
user_id string COMMENT ‘用户id’ ,
payment_way string COMMENT ‘支付方式’,
out_trade_no string COMMENT ‘支付流水号’,
create_time string COMMENT ‘创建时间’,
operate_time string COMMENT ‘操作时间’,
start_date string COMMENT ‘有效开始日期’,
end_date string COMMENT ‘有效结束日期’
) COMMENT ‘订单拉链临时表’
stored as parquet
location ‘/warehouse/gmall/dwd/dwd_order_info_his_tmp/’
tblproperties (“parquet.compression”=“snappy”);
2)导入脚本

hive (gmall)>
insert overwrite table dwd_order_info_his_tmp
select * from
(
select
id,
total_amount,
order_status,
user_id,
payment_way,
out_trade_no,
create_time,
operate_time,
‘2019-02-14’ start_date,
‘9999-99-99’ end_date
from dwd_order_info where dt=‘2019-02-14’

union all
select oh.id,
oh.total_amount,
oh.order_status,
oh.user_id,
oh.payment_way,
oh.out_trade_no,
oh.create_time,
oh.operate_time,
oh.start_date,
if(oi.id is null, oh.end_date, date_add(oi.dt,-1)) end_date
from dwd_order_info_his oh left join
(
select
*
from dwd_order_info
where dt=‘2019-02-14’
) oi
on oh.id=oi.id and oh.end_date=‘9999-99-99’
)his
order by his.id, start_date;
9.5.4 步骤3:把临时表覆盖给拉链表
1)导入数据
hive (gmall)>
insert overwrite table dwd_order_info_his
select * from dwd_order_info_his_tmp;
2)查询导入数据
hive (gmall)> select * from dwd_order_info_his;
9.5.5 整理为每日脚本

第10章 项目总结
10.1 熟悉8张表的业务字段,每张表记住3-5个字段
10.2 数仓理论
1)表的分类:实体表、维度表、事务型事实表、周期型事实表
2)表的同步策略:
实体表(全量)
维度表(全量)
事务型事实表(增量)
周期型事实表(新增和变化、拉链表)
3)范式理论:
一范式原则:属性不可切割;
二范式原则:不能存在部分函数依赖;
三范式原则:不能存在传递函数依赖;
4)数仓维度建模模型
星型模型,维度一层;
雪花模型,维度多层;
星座模型,多个事实表;
性能优先选择星型模型,灵活优先选择雪花模型。企业中星型模型多一些。
10.3 Sqoop参数
/opt/module/sqoop/bin/sqoop import
–connect
–username
–password
–target-dir
–delete-target-dir
–num-mappers
–fields-terminated-by
–query “$2” ’ and KaTeX parse error: Undefined control sequence: \t at position 1207: …terminated-by "\̲t̲" --export-dir …{day}" --staging-table app_cource_study_report_tmp --clear-staging-table --input-null-string ‘\N’
2)场景2:设置map数量为1个(不推荐,面试官想要的答案不只这个)
多个Map任务时,采用–staging-table方式,仍然可以解决数据一致性问题。
10.3.3 Sqoop底层运行的任务是什么
只有Map阶段,没有Reduce阶段的任务。
10.3.4 Sqoop数据导出的时候一次执行多长时间
Sqoop任务5分钟-2个小时的都有。取决于数据量。
10.4 需求指标分析
1)GMV:一段时间内的网站成交金额(包括付款和未付款)
计算:基于用户行为宽表,对订单总金额进行sum。
2)转化率:(先分别计算分子和分母,再相除)
(1)新增用户占活跃用户的比率;
cast(sum( uc.nmc)/sum( uc.dc)*100 as decimal(10,2)) new_m_ratio
(2)下单人数占活跃用户的比率;
sum(if(order_count>0,1,0)) order_count

cast(ua.order_count/uv.day_count*100 as decimal(10,2)) visitor2order_convert_ratio
(3)支付人数占下单人数的比率;
sum(if(payment_count>0,1,0)) payment_count

cast(ua.payment_count/ua.order_count*100 as decimal(10,2)) order2payment_convert_ratio
3)复购率:(先分别计算分子和分母,再相除)
sum(if(mn.order_count>=1,1,0)) buycount,
sum(if(mn.order_count>=2,1,0)) buyTwiceLast,
sum(if(mn.order_count>=2,1,0))/sum( if(mn.order_count>=1,1,0)) buyTwiceLastRatio,
sum(if(mn.order_count>=3,1,0)) buy3timeLast ,
sum(if(mn.order_count>=3,1,0))/sum( if(mn.order_count>=1,1,0)) buy3timeLastRatio ,
10.5 拉链表
1)通过关系型数据库的create time和operation time获取数据的新增和变化。
2)用临时拉链表解决Hive了中数据不能更新的问题。
10.6 Azkaban
1)每天集群运行多少job?
2)多个指标(200)6=1200(1000-2000个job)
3)每天集群运行多少个task? 1000
(5-8)=5000多个
4)任务挂了怎么办?运行成功或者失败都会发邮件
10.7 项目中表关系

猜你喜欢

转载自blog.csdn.net/w13716207404/article/details/103060619