=========== 如下 各维度表 最终合并为 客户消费模型表 ============
订单表
1.订单 主要信息表
1.订单 主要信息表 BDM层 bdm.itcast_bdm_order(时间分区)
2.订单 主要信息表 FDM层 fdm.itcast_fdm_order(时间分区)
2.订单 详细信息表
1.订单 详细信息表 BDM层 bdm.itcast_bdm_order_desc(时间分区)
2.订单 详细信息表 FDM层 fdm.itcast_fdm_order_desc(时间分区)
3.订单表 GDM层
订单宽表 GDM层 gdm.itcast_gdm_order(时间分区)
订单宽表 GDM层 = 订单 主要信息表 FDM层 + 订单 详细信息表 FDM层
----------------------------------------
订单中 商品信息表
1.订单中 商品信息表 BDM层 bdm.itcast_bdm_order_goods(时间分区)
2.订单中 商品信息表 FDM层 fdm.itcast_fdm_order_goods(时间分区)
----------------------------------------
客户订单地址表
客户订单地址表 GDM层 gdm.itcast_gdm_user_order_addr_model
----------------------------------------
购物车中 商品信息表
1.购物车中 商品信息表 BDM层 bdm.itcast_bdm_order_cart(时间分区)
2.购物车中 商品信息表 FDM层 fdm.itcast_fdm_order_cart(时间分区)
----------------------------------------
客户消费模型表(订单+购物车) GDM层(临时表)
没有时间分区,但是每次都会先 drop 临时表,再 CREATE 临时表 as select ...
1.临时表01(订单)
客户消费模型表 GDM层 gdm.itcast_gdm_user_consume_order_temp_01(临时表01)统计订单相关指标
客户消费模型表 GDM层 = 订单表 GDM层(时间分区) + 订单中商品信息表 FDM层(时间分区) + 客户订单地址表 GDM层
2.临时表02(购物车)
客户消费模型表 GDM层 gdm.itcast_gdm_user_consume_order_temp_02(临时表02) 统计购物车相关指标
客户消费模型表 GDM层 = 购物车中商品信息表 FDM层(时间分区)
3.临时表03(订单)
客户消费模型表 GDM层 gdm.itcast_gdm_user_consume_order_temp_03(临时表03) 统计订单中常用收货地址和常用支付方式
客户消费模型表 GDM层 = 订单表 GDM层(时间分区)+ 订单表 GDM层(时间分区)(订单表自身和自身union all)
4.临时表04
gdm.itcast_gdm_user_consume_order_temp_100(临时表04) = 客户消费模型表 GDM层(临时表01) + 客户消费模型表 GDM层(临时表02)
目的:仅为合并 订单表 和 购物车表 中所相同的的user_id为一个分组,并且最终合并结果中的每条数据均为不同的user_id
----------------------------------------
客户消费模型表(订单+购物车) GDM层
SQL目的:统计 订单 和 购物车 中相关消费指标。
当前该表中的“近30/60/90天的XX”等指标 仅为时间分区中每天的指标数据,因此还必须根据 where dt >= date_add(昨天日期时间, -29/-60/-90) 条件进行统计,
这样才能统计出真正的“近30/60/90天的XX”指标数据。
客户消费模型表 GDM层 gdm.itcast_gdm_user_consume_order(时间分区)
客户消费模型表 GDM层 = 临时表01 + 临时表02 + 临时表03 + 临时表04
====================== 订单表 =========================
订单表
1.订单 主要信息表
1.订单 主要信息表 BDM层 bdm.itcast_bdm_order(时间分区)
2.订单 主要信息表 FDM层 fdm.itcast_fdm_order(时间分区)
2.订单 详细信息表
1.订单 详细信息表 BDM层 bdm.itcast_bdm_order_desc(时间分区)
2.订单 详细信息表 FDM层 fdm.itcast_fdm_order_desc(时间分区)
3.订单表 GDM层
订单宽表 GDM层 gdm.itcast_gdm_order(时间分区)
订单宽表 GDM层 = 订单 主要信息表 FDM层 + 订单 详细信息表 FDM层
----------------------------------------
订单宽表 模型开发 BDM 层(源数据层)
--订单主要信息表 BDM 层(源数据层)
create database if not exists bdm;
create external table if not exists bdm.itcast_bdm_order(
order_id string, --订单ID
order_no string, --订单号
order_date string, --订单日期
user_id string, --用户ID
user_name string, --登录名
order_money double, --订单金额
order_type string, --订单类型
order_status string, --订单状态
pay_status string, --支付状态
pay_type string, --支付方式 1、在线支付,2、货到付款
order_source string, --订单来源
update_time timestamp --订单更新时间
) partitioned by (dt string)
row format delimited fields terminated by ','
lines terminated by '\n' //以某字符来分割每行
location '/business/itcast_bdm_order';
//添加分区
alter table bdm.itcast_bdm_order add partition (dt='2017-01-01') location '/business/itcast_bdm_order/dt=2017-01-01';
//把 BDM层源数据文件 导入到 BDM层 外部分区表中
hdfs dfs -put /root/source_data/itcast_bdm_order.txt /business/itcast_bdm_order/dt=2017-01-01/
----------------------------------------
订单 主要信息表 FDM层(对 BDM 源数据层的数据进行清洗和预处理)
--订单主要信息表FDM层
create database if not exists fdm;
create table if not exists fdm.itcast_fdm_order(
order_id string, --订单ID
order_no string, --订单号
order_date string, --订单日期
user_id string, --用户ID
user_name string, --登录名
order_money double, --订单金额
order_type string, --订单类型
order_status string, --订单状态
pay_status string, --支付状态
pay_type string, --支付方式 1、在线支付,2、货到付款
order_source string, --订单来源
update_time timestamp, --订单更新时间
dw_date timestamp
) partitioned by (dt string);
----------------------------------------
--加载 订单主要信息模型表BDM层(源数据层)数据 到 订单主要信息表 FDM层
insert overwrite table fdm.itcast_fdm_order partition(dt='2017-01-01')
select
t.order_id, --订单ID
t.order_no, --订单号
t.order_date, --订单日期
t.user_id, --用户ID
t.user_name, --登录名
t.order_money, --订单金额
t.order_type, --订单类型
t.order_status, --订单状态
t.pay_status, --支付状态
t.pay_type, --支付方式
t.order_source, --订单来源
t.update_time timestamp, --订单更新时间
from_unixtime(unix_timestamp()) dw_date // 作为操作时间:返回 Unix时间戳(Unix timestamp),表示将 Unix 时间戳字符串进行格式化
from bdm.itcast_bdm_order t where dt='2017-01-01';
----------------------------------------
订单 详细信息表 BDM 层(源数据层)
create database if not exists bdm;
create external table if not exists bdm.itcast_bdm_order_desc(
order_id string, --订单ID
order_no string, --订单号
consignee string, --收货人姓名
area_id string, --收货人地址ID
area_name string, --地址ID对应的地址段
address string, --收货人地址
mobile string, --收货人手机号
telphone string, --收货人电话
coupon_id bigint, --使用代金券ID
coupon_money double, --使用代金券金额
carriage_money double, --运费
create_time timestamp, --创建时间
update_time timestamp, --更新时间
dw_date timestamp
)partitioned by (dt string)
row format delimited fields terminated by ','
location '/business/itcast_bdm_order_desc';
//添加分区
alter table bdm.itcast_bdm_order_desc add partition (dt='2017-01-01') location '/business/itcast_bdm_order_desc/dt=2017-01-01';
//把 BDM层源数据文件 导入到 BDM层 外部分区表中
hdfs dfs -put /root/source_data/itcast_bdm_order_desc.txt /business/itcast_bdm_order_desc/dt=2017-01-01
----------------------------------------
订单 详细信息表 FDM层(对 BDM 源数据层的数据进行清洗和预处理)
create database if not exists fdm;
create table if not exists fdm.itcast_fdm_order_desc(
order_id string, --订单ID
order_no string, --订单号
consignee string, --收货人姓名
area_id string, --收货人地址ID
area_name string, --地址ID对应的地址段
address string, --收货人地址
mobile string, --收货人手机号
telphone string, --收货人电话
coupon_id bigint, --使用代金券ID
coupon_money double, --使用代金券金额
carriage_money double, --运费
create_time timestamp, --创建时间
update_time timestamp, --更新时间
dw_date timestamp
) partitioned by (dt string);
----------------------------------------
--加载 订单详细信息模型表 BDM层(源数据层)数据 到 订单详细信息表 FDM层
insert overwrite table fdm.itcast_fdm_order_desc partition(dt='2017-01-01')
select
t.order_id, --订单ID
t.order_no, --订单号
t.consignee, --收货人姓名
t.area_id, --收货人地址ID
t.area_name, --地址ID对应的地址段
t.address, --收货人地址
t.mobile, --收货人手机号
t.telphone, --收货人电话
t.coupon_id, --使用代金券ID
t.coupon_money, --使用代金券金额
t.carriage_money, --运费
t.create_time, --创建时间
t.update_time, --更新时间
from_unixtime(unix_timestamp()) dw_date // 作为操作时间:返回 Unix时间戳(Unix timestamp),表示将 Unix 时间戳字符串进行格式化
from bdm.itcast_bdm_order_desc t where dt='2017-01-01';
----------------------------------------
订单宽表模型 GDM 层(对 FDM 层数据 进行统计一些指标数据)
--订单宽表模型
create database if not exists gdm;
create table if not exists gdm.itcast_gdm_order(
order_id string,--订单ID
order_no string,--订单号
order_date string,--订单日期
user_id string,--用户ID
user_name string,--登录名
order_money double,--订单金额
order_type string,--订单类型
order_status string,--订单状态
pay_status string,--支付状态
pay_type string,--支付方式 1、在线支付,2、货到付款
order_source string,--订单来源
consignee string,--收货人姓名
area_id string,--收货人地址ID
area_name string,--地址ID对应的地址段(粒度到县)
address string,--收货人地址(手工填写的地址)
mobile string,--收货人手机号
telphone string,--收货人电话
coupon_id bigint,--使用代金券ID
coupon_money double,--使用代金券金额
carriage_money double,--运费
create_time timestamp,--创建时间
update_time timestamp,--更新时间
dw_date timestamp --操作时间
) partitioned by (dt string);
----------------------------------------
(关联查询)把 订单 主要信息表 FDM层 和 订单 详细信息表 FDM层 对同一订单信息 进行连接查询后返回的数据 加载到 订单宽表 FDM层
insert overwrite table gdm.itcast_gdm_order partition(dt='2017-01-01')
select
a.order_id, --订单ID
a.order_no, --订单号
a.order_date, --订单日期
a.user_id, --用户ID
a.user_name, --用户名
a.order_money, --订单金额
a.order_type, --订单类型
a.order_status, --订单状态
a.pay_status, --支付类型
a.pay_type, --支付方式
a.order_source, --订单来源
b.consignee, --收货人姓名
b.area_id, --收货人地址ID
b.area_name, --地址ID对应的地址段
b.address, --收货人地址
b.mobile, --收货人手机号
b.telphone, --收货人电话
b.coupon_id, --使用代金券ID
b.coupon_money, --使用代金券金额
b.carriage_money,--运费
b.create_time, --创建时间
b.update_time, --更新时间
from_unixtime(unix_timestamp()) dw_date // 作为操作时间:返回 Unix时间戳(Unix timestamp),表示将 Unix 时间戳字符串进行格式化
from (select * from fdm.itcast_fdm_order where dt='2017-01-01') a //订单 主要信息表 FDM层
join (select * from fdm.itcast_fdm_order_desc where dt='2017-01-01') b //订单 详细信息表 FDM层
on a.order_id=b.order_id; //以订单号ID作为两表连接查询的连接条件
=================== 订单中 商品信息表 ========================
订单中 商品信息表
1.订单中 商品信息表 BDM层 bdm.itcast_bdm_order_goods(时间分区)
2.订单中 商品信息表 FDM层 fdm.itcast_fdm_order_goods(时间分区)
----------------------------------------
订单商品信息表 BDM 层(源数据层)
-----订单商品信息表 BDM 层(源数据层)
create database if not exists bdm;
create external table if not exists bdm.itcast_bdm_order_goods(
user_id string,--用户ID
order_id string,--订单ID
order_no string,--订单号
sku_id bigint,--SKU编号
sku_name string,--SKU名称
goods_id bigint,--商品编号
goods_no string,--商品货号
goods_sn string,--商品条码
goods_name string,--商品名称
goods_amount bigint,--商品数量
size_id bigint,--尺码编号
size_name string,--尺码名称
colour_id bigint,--颜色ID
shop_id string,--店铺编号
shop_name string,--店铺名称
curr_price double,--售卖价格
market_price double,--市场价格
discount double,--折扣比例
cost_price double,--成本价格
cost_type string,--成本类型
warehouse string,--所在仓库
first_cart bigint,-- 一级分类ID
first_cart_name string,-- 一级分类名称
second_cart bigint,-- 二级分类ID
second_cart_name string,-- 二级分类名称
third_cart bigint,-- 三级分类ID
third_cart_name string,-- 三级分类名称
dw_date timestamp
) partitioned by (dt string)
row format delimited fields terminated by ','
lines terminated by '\n'
location '/business/itcast_bdm_order_goods';
//添加分区
alter table bdm.itcast_bdm_order_goods add partition (dt='2017-01-01') location '/business/itcast_bdm_order_goods/dt=2017-01-01';
//把 BDM层源数据文件 导入到 BDM层 外部分区表中
hdfs dfs -put /root/source_data/itcast_bdm_order_goods.txt /business/itcast_bdm_order_goods/dt=2017-01-01
----------------------------------------
订单商品信息表 FDM 层(对 BDM 源数据层的数据进行清洗和预处理)
-----订单商品信息表 FDM 层(对 BDM 源数据层的数据进行清洗和预处理)
create database if not exists fdm;
create table if not exists fdm.itcast_fdm_order_goods(
user_id string,--用户ID
order_id string,--订单ID
order_no string,--订单号
sku_id bigint,--SKU编号
sku_name string,--SKU名称
goods_id bigint,--商品编号
goods_no string,--商品货号
goods_sn string,--商品条码
goods_name string,--商品名称
goods_amount bigint,--商品数量
size_id bigint,--尺码编号
size_name string,--尺码名称
colour_id bigint,--颜色ID
shop_id string,--店铺编号
shop_name string,--店铺名称
curr_price double,--售卖价格
market_price double,--市场价格
discount double,--折扣比例
cost_price double,--成本价格
cost_type string,--成本类型
warehouse string,--所在仓库
first_cart bigint,-- 一级分类ID
first_cart_name string,-- 一级分类名称
second_cart bigint,-- 二级分类ID
second_cart_name string,-- 二级分类名称
third_cart bigint,-- 三级分类ID
third_cat_name string,-- 三级分类名称
dw_date timestamp
) partitioned by (dt string);
----------------------------------------
--加载 订单商品信息表 BDM层(源数据层)数据 到 订单商品信息表 FDM层
insert overwrite table fdm.itcast_fdm_order_goods partition(dt='2017-01-01')
select
t.user_id,--用户ID
t.order_id,--订单ID
t.order_no,--订单号
t.sku_id,--SKU编号
t.sku_name,--SKU名称
t.goods_id,--商品编号
t.goods_no,--商品货号
t.goods_sn,--商品条码
t.goods_name,--商品名称
t.goods_amount,--商品数量
t.size_id,--尺码编号
t.size_name,--尺码名称
t.colour_id,--颜色ID
t.shop_id,--店铺编号
t.shop_name,--店铺名称
t.curr_price,--售卖价格
t.market_price,--市场价格
t.discount,--折扣比例
t.cost_price,--成本价格
t.cost_type,--成本类型
t.warehouse,--所在仓库
t.first_cart,-- 一级分类ID
t.first_cart_name,-- 一级分类名称
t.second_cart,-- 二级分类ID
t.second_cart_name,-- 二级分类名称
t.third_cart,-- 三级分类ID
t.third_cart_name,-- 三级分类名称
from_unixtime(unix_timestamp()) dw_date
from bdm.itcast_bdm_order_goods t where dt='2017-01-01';
====================== 客户订单地址表 =================
客户订单地址表
客户订单地址表 GDM层 gdm.itcast_gdm_user_order_addr_model
----------------------------------------
客户订单地址模型表(用于标识是在哪里下单的)GDM 层(对 FDM 层数据 进行统计一些指标数据)
create database if not exists gdm;
create table if not exists gdm.itcast_gdm_user_order_addr_model(
user_id string, -- 客户ID
order_addr bigint, -- 1表示学校、2表示单位、3表示家里
user_order_flag string -- 关联标识
)
row format delimited fields terminated by ','
lines terminated by '\n';
load data local inpath '/root/source_data/itcast_gdm_user_order_addr_model.txt' overwrite into table gdm.itcast_gdm_user_order_addr_model;
====================== 购物车中 商品信息表 =================
购物车中 商品信息表
1.购物车中 商品信息表 BDM层 bdm.itcast_bdm_order_cart(时间分区)
2.购物车中 商品信息表 FDM层 fdm.itcast_fdm_order_cart(时间分区)
----------------------------------------
购物车订单表 BDM 层(源数据层)
create database if not exists bdm;
create external table if not exists bdm.itcast_bdm_order_cart(
id bigint,--ID
session_id string,--sessionID
user_id string,--用户ID
goods_id string,--商品ID
goods_num bigint,--商品数量
add_time string,--商品加入时间
cancle_time string,--商品取消时间
sumbit_time string,--商品提交时间
dw_date timestamp
) partitioned by (dt string)
row format delimited fields terminated by ','
lines terminated by '\n'
location '/business/itcast_bdm_order_cart';
//添加分区
alter table bdm.itcast_bdm_order_cart add partition (dt='2017-01-01') location '/business/itcast_bdm_order_cart/dt=2017-01-01';
//把 BDM层源数据文件 导入到 BDM层 外部分区表中
hdfs dfs -put /root/source_data/itcast_bdm_order_cart.txt /business/itcast_bdm_order_cart/dt=2017-01-01
----------------------------------------
购物车订单表 FDM 层(对 BDM 源数据层的数据进行清洗和预处理)
create database if not exists fdm;
create table if not exists fdm.itcast_fdm_order_cart(
id bigint,--ID
session_id string,--sessionID
user_id string,--用户ID
goods_id string,--商品ID
goods_num bigint,--商品数量
add_time string,--商品加入时间
cancle_time string,--商品取消时间
sumbit_time string,--商品提交时间
dw_date timestamp
) partitioned by (dt string);
----------------------------------------
--加载 购物车订单表 BDM层(源数据层)数据 到 购物车订单表 FDM层
insert overwrite table fdm.itcast_fdm_order_cart partition(dt='2017-01-01')
select
t.id,--ID
t.session_id,--sessionID
t.user_id,--用户ID
t.goods_id,--商品ID
t.goods_num ,--商品数量
t.add_time,--商品加入时间
t.cancle_time,--商品取消时间
t.sumbit_time,--商品提交时间
from_unixtime(unix_timestamp()) dw_date
from bdm.itcast_bdm_order_cart t where dt='2017-01-01';
================= 客户消费模型表:临时表 ====================
客户消费模型表(订单+购物车) GDM层(临时表)
没有时间分区,但是每次都会先 drop 临时表,再 CREATE 临时表 as select ...
1.临时表01(订单)
客户消费模型表 GDM层 gdm.itcast_gdm_user_consume_order_temp_01(临时表01)统计订单相关指标
客户消费模型表 GDM层 = 订单表 GDM层(时间分区) + 订单中商品信息表 FDM层(时间分区) + 客户订单地址表 GDM层
2.临时表02(购物车)
客户消费模型表 GDM层 gdm.itcast_gdm_user_consume_order_temp_02(临时表02) 统计购物车相关指标
客户消费模型表 GDM层 = 购物车中商品信息表 FDM层(时间分区)
3.临时表03(订单)
客户消费模型表 GDM层 gdm.itcast_gdm_user_consume_order_temp_03(临时表03) 统计订单中常用收货地址和常用支付方式
客户消费模型表 GDM层 = 订单表 GDM层(时间分区)+ 订单表 GDM层(时间分区)(订单表自身和自身union all)
4.临时表04
gdm.itcast_gdm_user_consume_order_temp_100(临时表04) = 客户消费模型表 GDM层(临时表01) + 客户消费模型表 GDM层(临时表02)
目的:仅为合并 订单表 和 购物车表 中所相同的的user_id为一个分组,并且最终合并结果中的每条数据均为不同的user_id
----------------------------------------
客户消费订单模型表 GDM 层(对 FDM 层数据 进行统计一些指标数据):
--统计订单相关指标(GDM 层的 临时表 itcast_gdm_user_consume_order_temp_01)
drop table if exists gdm.itcast_gdm_user_consume_order_temp_01;
第一个版本:(上课时的该版本有所缺失,订单商品信息表没有WHERE+时间分区)
CREATE TABLE gdm.itcast_gdm_user_consume_order_temp_01临时表 AS
SELECT ...FROM (SELECT ... FROM gdm.itcast_gdm_order订单宽表 WHERE dt = '2017-01-01') t
LEFT JOIN (SELECT ... FROM fdm.itcast_fdm_order_goods订单商品信息表) t1 ON (t.order_id = t1.order_id) //order_id 订单ID
LEFT JOIN (SELECT ... FROM gdm.itcast_gdm_user_order_addr_model客户订单位置表) t2 ON (t.user_id = t2.user_id) //user_id 用户ID
GROUP BY t.user_id ;
第二个版本:(该版本才为正确,订单商品信息表的WHERE加上了时间分区)
CREATE TABLE gdm.itcast_gdm_user_consume_order_temp_01临时表 AS
SELECT ...FROM (SELECT ... FROM gdm.itcast_gdm_order订单宽表 WHERE dt = '2017-01-01') t
LEFT JOIN (SELECT ... FROM fdm.itcast_fdm_order_goods订单商品信息表 WHERE dt = '2017-01-01') t1 ON (t.order_id = t1.order_id) //order_id 订单ID
LEFT JOIN (SELECT ... FROM gdm.itcast_gdm_user_order_addr_model客户订单位置表) t2 ON (t.user_id = t2.user_id) //user_id 用户ID
GROUP BY t.user_id ;
//下面很长的SQL语句的结构总结为上面的5行SQL结构
CREATE TABLE gdm.itcast_gdm_user_consume_order_temp_01 AS
SELECT
t.user_id,
MIN(order_date) first_order_time, --第一次消费时间:获取所有订单时间然后使用MIN()即能获取第一次消费时间
MAX(order_date) last_order_time, --最近一次消费时间:获取所有订单时间然后使用MAX()即能获取最近一次消费时间
DATEDIFF(MIN(order_date), '2017-01-01') first_order_ago, --首单距今时间:使用“2017-01-01”减去 MIN(订单时间) 即能获取首单距今时间
DATEDIFF(MAX(order_date), '2017-01-01') last_order_ago, --尾单距今时间:使用“2017-01-01”减去 MAX(订单时间) 即能获取尾单距今时间
SUM( //SUM():累加30天内的所有订单的总次数
CASE
WHEN t.dat_30 = 1 //1 表示订单是近30天内的
AND t.order_flag = 0 //0 表示订单为非退拒的
THEN 1
END
) month1_hg_order_cnt, --近30天购买次数(不含退拒)
SUM( //SUM():累加30天内的所有订单的总金额
CASE
WHEN t.dat_30 = 1 //1 表示订单是近30天内的
AND t.order_flag = 0 //0 表示订单为非退拒的
THEN t.order_money //返回订单购买金额
END
) month1_hg_order_amt, --近30天购买金额(不含退拒)
SUM( //SUM():累加60天内的所有订单的总次数
CASE
WHEN t.dat_60 = 1
AND t.order_flag = 0
THEN 1
END
) month2_hg_order_cnt, --近60天购买次数(不含退拒)
SUM( //SUM():累加60天内的所有订单的总金额
CASE
WHEN t.dat_60 = 1
AND t.order_flag = 0
THEN t.order_money
END
) month2_hg_order_amt, --近60天购买金额(不含退拒)
SUM( //SUM():累加90天内的所有订单的总次数
CASE
WHEN t.dat_90 = 1
AND t.order_flag = 0
THEN 1
END
) month3_hg_order_cnt, --近90天购买次数(不含退拒)
SUM( //SUM():累加90天内的所有订单的总金额
CASE
WHEN t.dat_90 = 1
AND t.order_flag = 0
THEN t.order_money
END
) month3_hg_order_amt, --近90天购买金额(不含退拒)
SUM(dat_30) month1_order_cnt, --近30天购买次数(含退拒)
SUM(
CASE
WHEN t.dat_30 = 1
THEN t.order_money
END
) month1_order_amt, --近30天购买金额(含退拒)
SUM(dat_60) month2_order_cnt, --近60天购买次数(含退拒)
SUM(
CASE
WHEN t.dat_60 = 1
THEN t.order_money
END
) month2_order_amt, --近60天购买金额(含退拒)
SUM(dat_90) month3_order_cnt, --近90天购买次数(含退拒)
SUM(
CASE
WHEN t.dat_90 = 1
THEN t.order_money
END
) month3_order_amt, --近90天购买金额(含退拒)
MAX(t.order_money) max_order_amt, --最大消费金额 //获取出所有的订单消费金额,然后使用MAX()获取最大的订单消费金额
MIN(t.order_money) min_order_amt, --最小消费金额 //获取出所有的订单消费金额,然后使用MIX()获取最小的订单消费金额
SUM( //SUM():累加所有非退拒的订单的总数
CASE
WHEN t.order_flag = 0 //0 表示订单为非退拒的
THEN 1
END
) total_order_cnt, --累计消费次数(不含退拒)
SUM( //SUM():累加所有非退拒的订单的总金额
CASE
WHEN t.order_flag = 0
THEN t.order_money //返回订单购买金额
END
) total_order_amt, --累计消费金额(不含退拒)
SUM(coupon_money) total_coupon_amt, --累计使用代金券金额 //SUM():累加所有代金券金额
SUM(t.order_money) / COUNT(1) user_avg_amt, --客单价(含退拒):客单价表示每个订单平均价格,通过所有商品总价格除以总订单数得出每个订单平均价格
//SUM():累加所有订单总金额。COUNT(1):统计订单的总数
0 month3_user_avg_amt, --近90天的客单价(含退拒)
0 common_address, --常用收获地址
0 common_paytype, --常用支付方式
0 month1_cart_cnt, --最近30天购物车次数
0 month1_cart_goods_cnt, --最近30天购物车商品件数
0 month1_cart_submit_cnt, --最近30天购物车提交商品件数
0 month1_order_rate, --最近30天购物车成功率
0 month1_cart_cancle_cnt, --最近30天购物车放弃件数
SUM( //SUM():累加所有退货商品的数量
CASE
WHEN t.order_status = 3 //订单状态为3表示退货
THEN t1.goods_amount //退货商品数量
END
) return_cnt, --退货商品数量
SUM( //SUM():累加所有退货商品的金额
CASE
WHEN t.order_status = 3 //订单状态为3表示退货
THEN t.order_money //退货商品金额
END
) return_amt, --退货商品金额
SUM( //SUM():累加所有拒收商品的数量
CASE
WHEN t.order_status = 4 //订单状态为4表示拒收
THEN t1.goods_amount //拒收商品数量
END
) reject_cnt, --拒收商品数量
SUM( //SUM():累加所有拒收商品的金额
CASE
WHEN t.order_status = 4 //订单状态为4表示拒收
THEN t.order_money //拒收商品金额
END
) reject_amt, --拒收商品金额
MAX( //MAX()获取最大的退货商品时间
CASE
WHEN t.order_status = 3 //订单状态为3表示退货
THEN t.order_date //退货商品时间
END
) last_return_time, --最近一次退货时间
SUM( //SUM():累加所有学校下单的总数
CASE
WHEN t2.order_addr = 1
THEN 1
END
) school_order_cnt, --学校下单总数
SUM( //SUM():累加所有单位下单的总数
CASE
WHEN t2.order_addr = 2
THEN 1
END
) company_order_cnt, --单位下单总数
SUM( //SUM():累加所有家里下单的总数
CASE
WHEN t2.order_addr = 3
THEN 1
END
) home_order_cnt, --家里下单总数
SUM( //SUM():累加所有上午下单的总数
CASE
WHEN t.order_hour >= 8
AND t.order_hour <= 11
THEN 1
END
) forenoon_order_cnt, --上午下单总数
SUM(//SUM():累加所有下午下单的总数
CASE
WHEN t.order_hour >= 12
AND t.order_hour <= 18
THEN 1
END
) afternoon_order_cnt, --下午下单总数
SUM(//SUM():累加所有晚上下单的总数
CASE
WHEN t.order_hour >= 19
AND t.order_hour <= 22
THEN 1
END
) night_order_cnt, --晚上下单总数
SUM(//SUM():累加所有凌晨下单的总数
CASE
WHEN t.order_hour >= 23
or t.order_hour <= 7
THEN 1
END
) morning_order_cnt --凌晨下单总数
FROM
(SELECT a.*,
(
CASE //如果order_date订单时间 大于“2017-01-01减去29天”并且小于“2017-01-01”的话,那么表示该订单便是(dat_30)30天之内的订单,那么便返回 1
WHEN order_date >= DATE_SUB('2017-01-01', 29)
AND order_date <= '2017-01-01'
THEN 1
END
) dat_30,
(
CASE //如果order_date订单时间 大于“2017-01-01减去59天”并且小于“2017-01-01”的话,那么表示该订单便是(dat_60)60天之内的订单,那么便返回 1
WHEN order_date >= DATE_SUB('2017-01-01', 59)
AND order_date <= '2017-01-01'
THEN 1
END
) dat_60,
(
CASE //如果order_date订单时间 大于“2017-01-01减去89天”并且小于“2017-01-01”的话,那么表示该订单便是(dat_90)90天之内的订单,那么便返回 1
WHEN order_date >= DATE_SUB('2017-01-01', 89)
AND order_date <= '2017-01-01'
THEN 1
END
) dat_90,
(
CASE //退货标识:3。拒收标识:4
WHEN a.order_status IN (3, 4)
THEN 1
ELSE 0
END
) order_flag, --退货与拒收标示
HOUR(order_date) order_hour //订单下单时的具体哪个小时,用于标识是上午、下午、晚上、凌晨下单
FROM gdm.itcast_gdm_order a
WHERE dt = '2017-01-01'
) t
LEFT JOIN
(SELECT
order_id, //订单ID
goods_amount //商品数量
FROM
fdm.itcast_fdm_order_goods) t1
ON (t.order_id = t1.order_id)
LEFT JOIN
(SELECT
user_id, //用户ID
order_addr //订单地址:是在哪里下单的
FROM
gdm.itcast_gdm_user_order_addr_model) t2
ON (t.user_id = t2.user_id)
GROUP BY t.user_id ;
----------------------------------------
客户消费订单模型表-临时表02:统计购物车相关指标 GDM 层(对 FDM 层数据 进行统计一些指标数据)
1.MySQL表 购物车表 数据 分为 2种:
1.当前仍在购买车中的商品
2.已经不在购买车中的商品(包括 被移除的商品、成功交易的商品)
2.MySQL表 购物车表中 每个商品的 重要字段结构:
商品添加进购物车的时间
商品移出购物车的时间
商品成功支付的时间
商品名(SKU名)
商品数量
3.Hive表 每天定时所统计的购物车表源数据中 分为 3种:
1.当天购买车中 等待支付的商品
2.当天购买车中 被移除的商品
3.当天购买车中 成功交易的商品
4.第一种统计版本(上课时所使用的版本):
CREATE TABLE 表名 AS SELECT FROM 表名 WHERE dt=昨天 and (前第30天 <= add_time <= 昨天) GROUP BY user_id
SQL目的:仅统计 近30天之内 被添加进购物车的商品,其中包含等待支付的商品、被移除的商品、成功交易的商品,但不统计 30天之前 已经被添加进购物车的商品。
5.第二种统计版本(推荐实际使用的版本)
CREATE TABLE 表名 AS SELECT FROM 表名 WHERE dt=昨天 GROUP BY user_id
SQL目的:只要是被添加进购物车的商品都进行统计,而不仅限 近30天之内 被添加进购物车的商品
drop table if exists gdm.itcast_gdm_user_consume_order_temp_02;
CREATE TABLE gdm.itcast_gdm_user_consume_order_temp_02 AS
SELECT
user_id,
COUNT(1) month1_cart_cnt, --最近30天购物车次数 //COUNT(1):统计购物车中的 不同商品种类数(SKU数)
SUM(goods_num) month1_cart_goods_cnt, --最近30天购物车商品件数//SUM():累加购物车中所有商品总数
SUM( //SUM():累加购物车中所提交的成功支付的商品总数
CASE
WHEN sumbit_time <> '' // <> '' 表示不等于空字符串,即商品提交时间不等于
THEN goods_num
ELSE 0
END
) month1_cart_submit_cnt, --最近30天购物车提交的成功支付商品件数
SUM(//通过商品提交的数量除以购物车中商品总数得出购物车中商品成交的成功率
CASE
WHEN sumbit_time <> ''
THEN goods_num
ELSE 0
END
)/SUM(goods_num) month1_cart_rate, --最近30天购物车成功率 //商品提交的成功支付的数量除以购物车中商品总数
SUM( //SUM():累加购物车中所取消商品的总数
CASE
WHEN cancle_time <> ''
THEN goods_num
ELSE 0
END
) month1_cart_cancle_cnt --最近30天购物车放弃件数(所移除的商品总数)
FROM
fdm.itcast_fdm_order_cart
WHERE dt = '2017-01-01'
//时间日期转化函数to_date:可把字符串时间转换为日期类型时间。
//添加商品时间 大于“2017-01-01减去29天”并且小于“2017-01-01”的话,那么表示该商品便是(dat_30)30天之内添加到购物车中的商品
AND to_date (add_time) >= DATE_SUB('2017-01-01', 29)
AND to_date (add_time) <= '2017-01-01'
GROUP BY user_id ;
----------------------------------------
客户消费订单模型表-临时表03:统计常用收货地址和常用支付方式 GDM 层(对 FDM 层数据 进行统计一些指标数据)
drop table if exists gdm.itcast_gdm_user_consume_order_temp_03;
create table gdm.itcast_gdm_user_consume_order_temp_03临时表
as select ... from (select ... from (select ... from gdm.itcast_gdm_order订单宽表 where dt = '2017-01-01' group by ...
union all
select ... from gdm.itcast_gdm_order订单宽表 where dt = '2017-01-01' group by ...) ) ;
//下面长长的SQL简化为上面的SQL结构,下面的SQL目的:取出每个收货地址分组中使用最多的收货地址,或每个支付方式分组中使用最多的支付方式
create table gdm.itcast_gdm_user_consume_order_temp_03 as
select
t.user_id,
t.con,
t.type,
t.cnt
from
(select
b.user_id,
b.con,
b.type,
b.cnt, //type:代表收货地址address或支付类型pay_type。别名rn 表示每个分组中的顺序序号,从1开始。
row_number() over(distribute by b.user_id, b.type //把相同用户id和相同收货地址address分为一组,或把相同用户id和相同支付类型pay_type分为一组
sort by b.cnt, b.type desc) rn //先按照使用次数cnt进行降序排序,如果使用次数cnt相同则按照type收货地址或支付类型进行降序排序
from
(select //该SQL目的:统计每个用户对应所使用的每个收货地址的使用次数 //coalesce(字段, '') 如果字段列的值为null空的话,则替换为空字符串
a.user_id, concat(coalesce(area_name, ''), coalesce(address, '')) con, //concat 把多个字段列数据 拼接为 一个字符串
'address' type, //给收货地址字段address取别名为type
count(1) cnt //统计每个用户对应所使用的每个收货地址的使用次数
from gdm.itcast_gdm_order a
where dt = '2017-01-01'
//对每个用户进行分组的同时,还对每个用户所对应使用的每个收货地址进行分组,意思即把相同用户id和相同收货地址分为一组
group by a.user_id, concat(coalesce(area_name, ''), coalesce(address, ''))
union all //合并两个或多个 SELECT 语句的结果集,并且不会对合并后的结果集进行去重
select //该SQL目的:统计每个用户对应所使用的每个支付方式的使用次数
a.user_id, a.pay_type con,
'pay_type' type, //给支付类型字段pay_type取别名为type
count(1) cnt //统计每个用户对应所使用的每个支付方式的使用次数
from gdm.itcast_gdm_order a
where dt = '2017-01-01'
//对每个用户进行分组的同时,还对每个用户所对应使用的每个支付方式进行分组,意思即把相同用户id和相同支付方式分为一组
group by a.user_id, a.pay_type
) b
) t
where t.rn = 1 ; //别名rn 表示每个分组中的顺序序号,从1开始。此处取出每个收货地址分组中使用最多的收货地址,或每个支付方式分组中使用最多的支付方式
注意:
select a.user_id, concat(coalesce(area_name, ''), coalesce(address, '')) con, 'address' type, count(1) cnt
group by a.user_id, concat(coalesce(area_name, ''), coalesce(address, ''))
union all
select a.user_id, a.pay_type con, 'pay_type' type, count(1) cnt group by a.user_id, a.pay_type
上面的SQL语句解析如下:
select 用户id,拼接收货地址,收货地址,收货地址的使用次数 from 订单宽表 group by 用户id,拼接收货地址
union all
select 用户id,支付方式,支付方式,支付方式的使用次数 from 订单宽表 group by 用户id,支付方式
解析:为的是使用union all把两张表合并时,把收货地址字段address和支付类型字段pay_type都合并为一列,取该列名为type,
那么便可以直接对type字段进行分组,也即是对收货地址字段address和支付类型字段pay_type同时进行各自的分组。
----------------------------------------
订单表 和 购物车表 整合(临时表)目的:仅为合并两表中所相同的的user_id为一个分组,并且最终合并结果中的每条数据均为不同的user_id
drop table if exists gdm.itcast_gdm_user_consume_order_temp_100;
create table gdm.itcast_gdm_user_consume_order_temp_100 as
select
a.user_id
from
(select user_id
from gdm.itcast_gdm_user_consume_order_temp_01 //统计 订单 相关指标的 临时表01
union all
select user_id
from gdm.itcast_gdm_user_consume_order_temp_02 //统计 购物车 相关指标的 临时表02
) a
group by a.user_id ;
==================== 客户消费模型表:汇总数据 ==================
客户消费模型表(订单+购物车) GDM层
SQL目的:统计 订单 和 购物车 中相关消费指标。
当前该表中的“近30/60/90天的XX”等指标 仅为时间分区中每天的指标数据,因此还必须根据 where dt >= date_add(昨天日期时间, -29/-60/-90) 条件进行统计,
这样才能统计出真正的“近30/60/90天的XX”指标数据。
客户消费模型表 GDM层 gdm.itcast_gdm_user_consume_order(时间分区)
客户消费模型表 GDM层 = 临时表01 + 临时表02 + 临时表03 + 临时表04
----------------------------------------
客户消费订单表模型 GDM 层(对 FDM 层数据 进行统计一些指标数据)
SQL目的:统计 订单 和 购物车 中相关消费指标。
当前该表中的“近30/60/90天的XX”等指标 仅为时间分区中每天的指标数据,因此还必须根据 where dt >= date_add(昨天日期时间, -29/-60/-90) 条件进行统计,
这样才能统计出真正的“近30/60/90天的XX”指标数据。
create database if not exists gdm;
create table if not exists gdm.itcast_gdm_user_consume_order(
user_id string, --客户ID
first_order_time timestamp, --第一次消费时间
last_order_time timestamp, --最近一次消费时间
first_order_ago bigint, --首单距今时间
last_order_ago bigint, --尾单距今时间
month1_hg_order_cnt bigint, --近30天购买次数(不含退拒)
month1_hg_order_amt double, --近30天购买金额(不含退拒)
month2_hg_order_cnt bigint, --近60天购买次数(不含退拒)
month2_hg_order_amt double, --近60天购买金额(不含退拒)
month3_hg_order_cnt bigint, --近90天购买次数(不含退拒)
month3_hg_order_amt double, --近90天购买金额(不含退拒)
month1_order_cnt bigint, --近30天购买次数(含退拒)
month1_order_amt double, --近30天购买金额(含退拒)
month2_order_cnt bigint, --近60天购买次数(含退拒)
month2_order_amt double, --近60天购买金额(含退拒)
month3_order_cnt bigint, --近90天购买次数(含退拒)
month3_order_amt double, --近90天购买金额(含退拒)
max_order_amt double, --最大消费金额
min_order_amt double, --最小消费金额
total_order_cnt bigint, --累计消费次数(不含退拒)
total_order_amt double, --累计消费金额(不含退拒)
user_avg_amt double, --客单价(含退拒)//客单价表示每个订单平均价格,通过所有商品总价格除以总订单数得出每个订单平均价格
month3_user_avg_amt double, --近90天的客单价
common_address string, --常用收货地址
common_paytype string, --常用支付方式
month1_cart_cnt bigint, --近30天购物车的次数
month1_cart_goods_cnt bigint, --近30天购物车商品件数
month1_cart_submit_cnt bigint, --近30天购物车提交商品件数(成功交易)
month1_cart_rate double, --近30天购物车成功率,通过上面的 购物车提交商品总件数 除以 购物车商品总件数 得出
month1_cart_cancle_cnt double, --近30天购物车放弃件数
return_cnt bigint, --退货商品数量
return_amt double, --退货商品金额
reject_cnt bigint, --拒收商品数量
reject_amt double, --拒收商品金额
last_return_time timestamp, --最近一次退货时间
school_order_cnt bigint, --学校下单总数
company_order_cnt bigint, --单位下单总数
home_order_cnt bigint, --家里下单总数
forenoon_order_cnt bigint, --上午下单总数
afternoon_order_cnt bigint, --下午下单总数
night_order_cnt bigint, --晚上下单总数
morning_order_cnt bigint, --凌晨下单总数
dw_date timestamp
) partitioned by (dt string);
----------------------------------------
//加载数据到 GDM层的 客户消费订单表
INSERT overwrite TABLE gdm.itcast_gdm_user_consume_order PARTITION (dt = '2017-01-01')
SELECT
t.user_id, --客户ID
t1.first_order_time, --第一次消费时间
t1.last_order_time, --最近一次消费时间
t1.first_order_ago, --首单距今时间
t1.last_order_ago, --尾单距今时间
t1.month1_hg_order_cnt, --近30天购买次数(不含退拒)
t1.month1_hg_order_amt, --近30天购买金额(不含退拒)
t1.month2_hg_order_cnt, --近60天购买次数(不含退拒)
t1.month2_hg_order_amt, --近60天购买金额(不含退拒)
t1.month3_hg_order_cnt, --近90天购买次数(不含退拒)
t1.month3_hg_order_amt, --近90天购买金额(不含退拒)
t1.month1_order_cnt, --近30天购买次数(含退拒)
t1.month1_order_amt, --近30天购买金额(含退拒)
t1.month2_order_cnt, --近60天购买次数(含退拒)
t1.month2_order_amt, --近60天购买金额(含退拒)
t1.month3_order_cnt, --近90天购买次数(含退拒)
t1.month3_order_amt, --近90天购买金额(含退拒)
t1.max_order_amt, --最大消费金额
t1.min_order_amt, --最小消费金额
t1.total_order_cnt, --累计消费次数(不含退拒)
t1.total_order_amt, --累计消费金额(不含退拒)
t1.user_avg_amt, --客单价(含退拒)
(
CASE
WHEN t1.month3_order_cnt <> 0 // <> 0 表示 不等于0
THEN t1.month3_order_amt / t1.month3_order_cnt // 近90天购买金额 除以 近90天购买次数 = 近90天的客单价(含退拒)
ELSE 0
END
) month3_user_avg_amt, --近90天的客单价(含退拒)
t3.common_address, --常用收货地址
t3.common_paytype, --常用支付方式
t2.month1_cart_cnt, --近30天购物车的次数
t2.month1_cart_goods_cnt, --近30天购物车商品件数
t2.month1_cart_submit_cnt, --近30天购物车提交商品件数
t2.month1_cart_rate, --近30天购物车成功率
t2.month1_cart_cancle_cnt, --近30天购物车放弃件数
t1.return_cnt, --退货商品数量
t1.return_amt, --退货商品金额
t1.reject_cnt, --拒收商品数量
t1.reject_amt, --拒收商品金额
t1.last_return_time, --最近一次退货时间
t1.school_order_cnt, --学校下单总数
t1.company_order_cnt, --单位下单总数
t1.home_order_cnt, --家里下单总数
t1.forenoon_order_cnt, --上午下单总数
t1.afternoon_order_cnt, --下午下单总数
t1.night_order_cnt, --晚上下单总数
t1.morning_order_cnt, --凌晨下单总数
FROM_UNIXTIME(UNIX_TIMESTAMP()) dw_date // 作为操作时间:返回 Unix时间戳(Unix timestamp),表示将 Unix 时间戳字符串进行格式化
FROM
gdm.itcast_gdm_user_consume_order_temp_100 t
LEFT JOIN gdm.itcast_gdm_user_consume_order_temp_01 t1 //统计 订单 相关指标的 临时表01
ON (t.user_id = t1.user_id)
LEFT JOIN gdm.itcast_gdm_user_consume_order_temp_02 t2 //统计 购物车 相关指标的 临时表02
ON (t.user_id = t2.user_id)
LEFT JOIN
(SELECT user_id,
MAX(CASE
WHEN type = 'address'
THEN con
END) common_address,
MAX(CASE
WHEN type = 'pay_type'
THEN con
END) common_paytype
FROM gdm.itcast_gdm_user_consume_order_temp_03 //统计 常用收货地址和常用支付方式 的临时表03
group by user_id) t3
ON (t.user_id = t3.user_id);