数仓之订单详情事实表【价格分摊】
1.创建订单详情事实表
drop table if exists dwd_fact_order_detail;
create external table dwd_fact_order_detail (
`id` string COMMENT '订单编号',
`order_id` string COMMENT '订单号',
`user_id` string COMMENT '用户id',
`sku_id` string COMMENT 'sku商品id',
`sku_name` string COMMENT '商品名称',
`order_price` decimal(16,2) COMMENT '商品价格',
`sku_num` bigint COMMENT '商品数量',
`create_time` string COMMENT '创建时间',
`province_id` string COMMENT '省份ID',
`source_type` string COMMENT '来源类型',
`source_id` string COMMENT '来源编号',
`original_amount_d` decimal(20,2) COMMENT '原始价格分摊',
`final_amount_d` decimal(20,2) COMMENT '购买价格分摊',
`feight_fee_d` decimal(20,2) COMMENT '分摊运费',
`benefit_reduce_amount_d` decimal(20,2) COMMENT '分摊优惠'
) COMMENT '订单明细事实表表'
PARTITIONED BY (`dt` string)--按天进行分区
stored as parquet--列式存储parquet
location '/warehouse/gmall/dwd/dwd_fact_order_detail/'--HDFS数据的位置
tblproperties ("parquet.compression"="lzo");--采用LZO对数据压缩
2.编写脚本
#!/bin/bash
#指定数据库&hive路径
APP=gmall
hive=/opt/module/hive-3.1.2/bin/hive
#如果是输入的日期按照取输入日期;如果没输入日期取当前时间的前一天
if [ -n "$2" ] ;then
do_date=$2
else
do_date=`date -d "-1 day" +%F`
fi
sql1="
set mapreduce.job.queuename=hive;
set hive.exec.dynamic.partition.mode=nonstrict;
set hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat;
#订单详情表
insert overwrite table ${APP}.dwd_fact_order_detail partition(dt='$do_date')
select
id,
order_id,
user_id,
sku_id,
sku_num,
order_price,
sku_num,
create_time,
province_id,
source_type,
source_id,
original_amount_d,--原始价格分摊=商品价格*商品数量
if(rn=1,final_total_amount-(sum_div_final_amount-final_amount_d),final_amount_d),--购买价格分摊
if(rn=1,feight_fee-(sum_div_feight_fee-feight_fee_d),feight_fee_d),--分摊运费
if(rn=1,benefit_reduce_amount-(sum_div_benefit_reduce_amount-benefit_reduce_amount_d),benefit_reduce_amount_d)--分摊优惠
from
(
select
od.id,
od.order_id,
od.user_id,
od.sku_id,
od.sku_name,
od.order_price,
od.sku_num,
od.create_time,
oi.province_id,
od.source_type,
od.source_id,
round(od.order_price*od.sku_num,2) original_amount_d, --原始价格分摊 = 商品价格*商品数量
round(od.order_price*od.sku_num/oi.original_total_amount*oi.final_total_amount,2) final_amount_d,--购买价格分摊 = (商品价格*商品数量/原价金额)*订单金额
round(od.order_price*od.sku_num/oi.original_total_amount*oi.feight_fee,2) feight_fee_d,--运费分摊 = (商品价格*商品数量/原价金额)*订单运费
round(od.order_price*od.sku_num/oi.original_total_amount*oi.benefit_reduce_amount,2) benefit_reduce_amount_d,--优惠分摊=(商品价格*商品数量/原价金额)*订单优惠金额
row_number() over(partition by od.order_id order by od.id desc) rn,
oi.final_total_amount,--订单金额
oi.feight_fee,--订单运费
oi.benefit_reduce_amount,--订单优惠金额
sum(round(od.order_price*od.sku_num/oi.original_total_amount*oi.final_total_amount,2)) over(partition by od.order_id) sum_div_final_amount,--购买价格的总和
sum(round(od.order_price*od.sku_num/oi.original_total_amount*oi.feight_fee,2)) over(partition by od.order_id) sum_div_feight_fee,--分摊运费的总和
sum(round(od.order_price*od.sku_num/oi.original_total_amount*oi.benefit_reduce_amount,2)) over(partition by od.order_id) sum_div_benefit_reduce_amount--分摊优惠的总和
from
(
select * from ${APP}.ods_order_detail where dt='$do_date'
) od
join
(
select * from ${APP}.ods_order_info where dt='$do_date'
) oi
on od.order_id=oi.id
)t1";
#sql的运行
$hive -e "$sql"
3.思路
1.查询 ods层的[订单表+订单详情表]进行关联
2.计算[原始价格分摊,购买价格分摊,运费分摊,优惠分摊]
3.计算[购买价格运费的总和,分摊运费的总和,分摊优惠的总和]
4.考虑特殊情况:分摊有余
取商品开窗的第一条数据:[订单总额-购买价格的总和+第一条的购买价格分摊]
if(rn=1,final_total_amount-(sum_div_final_amount-final_amount_d),final_amount_d)
5.重新写入覆盖到dwd层订单详情表