电商离线数据处理实训-hive数仓
任务一:数据抽取
编写Scala代码,使用Spark将MySQL的shtd_store库中表user_info、sku_info、base_province、base_region、order_info、order_detail的数据增量抽取到Hive的ods库中对应表user_info、sku_info、base_province、base_region、order_info、order_detail中。
1、抽取shtd_store库中user_info的增量数据进入Hive的ods库中表user_info。根据ods.user_info表中operate_time或create_time作为增量字段(即MySQL中每条数据取这两个时间中较大的那个时间作为增量字段去和ods里的这两个字段中较大的时间进行比较),只将新增的数据抽入,字段名称、类型不变,同时添加静态分区,分区字段为etl_date,类型为String,且值为当前比赛日的前一天日期(分区字段格式为yyyyMMdd)。使用hive cli执行show partitions ods.user_info命令,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;
2、抽取shtd_store库中sku_info的增量数据进入Hive的ods库中表sku_info。根据ods.sku_info表中create_time作为增量字段,只将新增的数据抽入,字段名称、类型不变,同时添加静态分区,分区字段为etl_date,类型为String,且值为当前比赛日的前一天日期(分区字段格式为yyyyMMdd)。使用hive cli执行show partitions ods.sku_info命令,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;
3、抽取shtd_store库中base_province的增量数据进入Hive的ods库中表base_province。根据ods.base_province表中id作为增量字段,只将新增的数据抽入,字段名称、类型不变并添加字段create_time取当前时间,同时添加静态分区,分区字段为etl_date,类型为String,且值为当前比赛日的前一天日期(分区字段格式为yyyyMMdd)。使用hive cli执行show partitions ods.base_province命令,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;
4、抽取shtd_store库中base_region的增量数据进入Hive的ods库中表base_region。根据ods.base_region表中id作为增量字段,只将新增的数据抽入,字段名称、类型不变并添加字段create_time取当前时间,同时添加静态分区,分区字段为etl_date,类型为String,且值为当前比赛日的前一天日期(分区字段格式为yyyyMMdd)。使用hive cli执行show partitions ods.base_region命令,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;
5、抽取shtd_store库中order_info的增量数据进入Hive的ods库中表order_info,根据ods.order_info表中operate_time或create_time作为增量字段(即MySQL中每条数据取这两个时间中较大的那个时间作为增量字段去和ods里的这两个字段中较大的时间进行比较),只将新增的数据抽入,字段名称、类型不变,同时添加静态分区,分区字段为etl_date,类型为String,且值为当前比赛日的前一天日期(分区字段格式为yyyyMMdd)。使用hive cli执行show partitions ods.order_info命令,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;
6、抽取shtd_store库中order_detail的增量数据进入Hive的ods库中表order_detail,根据ods.order_detail表中create_time作为增量字段,只将新增的数据抽入,字段名称、类型不变,同时添加静态分区,分区字段为etl_date,类型为String,且值为当前比赛日的前一天日期(分区字段格式为yyyyMMdd)。使用hive cli执行show partitions ods.order_detail命令,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下。
任务二:数据清洗
编写Scala代码,使用Spark将ods库中相应表数据全量抽取到Hive的dwd库中对应表中。表中有涉及到timestamp类型的,均要求按照yyyy-MM-dd HH:mm:ss,不记录毫秒数,若原数据中只有年月日,则在时分秒的位置添加00:00:00,添加之后使其符合yyyy-MM-dd HH:mm:ss。
1、抽取ods库中user_info表中昨天的分区(任务一生成的分区)数据,并结合dim_user_info最新分区现有的数据,根据id合并数据到dwd库中dim_user_info的分区表(合并是指对dwd层数据进行插入或修改,需修改的数据以id为合并字段,根据operate_time排序取最新的一条),分区字段为etl_date且值与ods库的相对应表该值相等,同时若operate_time为空,则用create_time填充,并添加dwd_insert_user、dwd_insert_time、dwd_modify_user、dwd_modify_time四列,其中dwd_insert_user、dwd_modify_user均填写“user1”。若该条记录第一次进入数仓dwd层则dwd_insert_time、dwd_modify_time均存当前操作时间,并进行数据类型转换。若该数据在进入dwd层时发生了合并修改,则dwd_insert_time时间不变,dwd_modify_time存当前操作时间,其余列存最新的值。使用hive cli执行show partitions dwd.dim_user_info命令,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;
2、抽取ods库sku_info表中昨天的分区(任务一生成的分区)数据,并结合dim_sku_info最新分区现有的数据,根据id合并数据到dwd库中dim_sku_info的分区表(合并是指对dwd层数据进行插入或修改,需修改的数据以id为合并字段,根据create_time排序取最新的一条),分区字段为etl_date且值与ods库的相对应表该值相等,并添加dwd_insert_user、dwd_insert_time、dwd_modify_user、dwd_modify_time四列,其中dwd_insert_user、dwd_modify_user均填写“user1”。若该条数据第一次进入数仓dwd层则dwd_insert_time、dwd_modify_time均填写当前操作时间,并进行数据类型转换。若该数据在进入dwd层时发生了合并修改,则dwd_insert_time时间不变,dwd_modify_time存当前操作时间,其余列存最新的值。使用hive cli查询表dim_sku_info的字段id、sku_desc、dwd_insert_user、dwd_modify_time、etl_date,条件为最新分区的数据,id大于等于15且小于等于20,并且按照id升序排序,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;
3、抽取ods库base_province表中昨天的分区(任务一生成的分区)数据,并结合dim_province最新分区现有的数据,根据id合并数据到dwd库中dim_province的分区表(合并是指对dwd层数据进行插入或修改,需修改的数据以id为合并字段,根据create_time排序取最新的一条),分区字段为etl_date且值与ods库的相对应表该值相等,并添加dwd_insert_user、dwd_insert_time、dwd_modify_user、dwd_modify_time四列,其中dwd_insert_user、dwd_modify_user均填写“user1”。若该条数据第一次进入数仓dwd层则dwd_insert_time、dwd_modify_time均填写当前操作时间,并进行数据类型转换。若该数据在进入dwd层时发生了合并修改,则dwd_insert_time时间不变,dwd_modify_time存当前操作时间,其余列存最新的值。使用hive cli在表dwd.dim_province最新分区中,查询该分区中数据的条数,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;
4、抽取ods库base_region表中昨天的分区(任务一生成的分区)数据,并结合dim_region最新分区现有的数据,根据id合并数据到dwd库中的分区表(合并是指对dwd层数据进行插入或修改,需修改的数据以id为合并字段,根据create_time排序取最新的一条),分区字段为etl_date且值与ods库的相对应表该值相等,并添加dwd_insert_user、dwd_insert_time、dwd_modify_user、dwd_modify_time四列,其中dwd_insert_user、dwd_modify_user均填写“user1”。若该条数据第一次进入数仓dwd层则dwd_insert_time、dwd_modify_time均填写当前操作时间,并进行数据类型转换。若该数据在进入dwd层时发生了合并修改,则dwd_insert_time时间不变,dwd_modify_time存当前操作时间,其余列存最新的值。使用hive cli在表dwd.dim_region最新分区中,查询该分区中数据的条数,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;
5、将ods库中order_info表昨天的分区(任务一生成的分区)数据抽取到dwd库中fact_order_info的动态分区表,分区字段为etl_date,类型为String,取create_time值并将格式转换为yyyyMMdd,同时若operate_time为空,则用create_time填充,并添加dwd_insert_user、dwd_insert_time、dwd_modify_user、dwd_modify_time四列,其中dwd_insert_user、dwd_modify_user均填写“user1”,dwd_insert_time、dwd_modify_time均填写当前操作时间,并进行数据类型转换。使用hive cli执行show partitions dwd.fact_order_info命令,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;
6、将ods库中order_detail表昨天的分区(任务一中生成的分区)数据抽取到dwd库中fact_order_detail的动态分区表,分区字段为etl_date,类型为String,取create_time值并将格式转换为yyyyMMdd,并添加dwd_insert_user、dwd_insert_time、dwd_modify_user、dwd_modify_time四列,其中dwd_insert_user、dwd_modify_user均填写“user1”,dwd_insert_time、dwd_modify_time均填写当前操作时间,并进行数据类型转换。使用hive cli执行show partitions dwd.fact_order_detail命令,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下。
任务三:指标计算
编写Scala代码,使用Spark计算相关指标。
注:在指标计算中,不考虑订单信息表中order_status字段的值,将所有订单视为有效订单。计算订单金额或订单总金额时只使用final_total_amount字段。需注意dwd所有的维表取最新的分区。
provinceeverymonth
1、 根据dwd层表统计每个省份、每个地区、每个月下单的数量和下单的总金额,存入MySQL数据库shtd_result的provinceeverymonth表中(表结构如下),然后在Linux的MySQL命令行中根据订单总数、订单总金额、省份表主键均为降序排序,查询出前5条,将SQL语句复制粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下,将执行结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;
字段 | 类型 | 中文含义 | 备注 |
provinceid | int | 省份表主键 | |
provincename | text | 省份名称 | |
regionid | int | 地区表主键 | |
regionname | text | 地区名称 | |
totalconsumption | double | 订单总金额 | 当月订单总金额 |
totalorder | int | 订单总数 | 当月订单总数 |
year | int | 年 | 订单产生的年 |
month | int | 月 | 订单产生的月 |
user_consumption_day_aggr
2、 根据dwd层表统计每人每天下单的数量和下单的总金额,存入dws层的user_consumption_day_aggr表中(表结构如下),然后使用hive cli按照客户主键、订单总金额均为降序排序,查询出前5条,将SQL语句与执行结果截图粘贴至对应报告中;
字段 | 类型 | 中文含义 | 备注 |
user_id | int | 客户主键 | |
user_name | string | 客户名称 | |
total_amount | double | 订单总金额 | 当天订单总金额 |
total_count | int | 订单总数 | 当天订单总数 |
year | int | 年 | 订单产生的年,为动态分区字段 |
month | int | 月 | 订单产生的月,为动态分区字段 |
day | int | 日 | 订单产生的日,为动态分区字段 |
provinceavgcmp
3、请根据dwd层表计算出2020年4月每个省份的平均订单金额和所有省份平均订单金额相比较结果(“高/低/相同”),存入MySQL数据库shtd_result的provinceavgcmp表(表结构如下)中,然后在Linux的MySQL命令行中根据省份表主键、该省平均订单金额均为降序排序,查询出前5条,将SQL语句复制粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下,将执行结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;
字段 | 类型 | 中文含义 | 备注 |
provinceid | int | 省份表主键 | |
provincename | text | 省份名称 | |
provinceavgconsumption | double | 该省平均订单金额 | |
allprovinceavgconsumption | double | 所有省平均订单金额 | |
comparison | text | 比较结果 | 该省平均订单金额和所有省平均订单金额比较结果,值为:高/低/相同 |
usercontinueorder
4、根据dwd层表统计在两天内连续下单并且下单金额保持增长的用户,存入MySQL数据库shtd_result的usercontinueorder表(表结构如下)中,然后在Linux的MySQL命令行中根据订单总数、订单总金额、客户主键均为降序排序,查询出前5条,将SQL语句复制粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下,将执行结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下。
字段 | 类型 | 中文含义 | 备注 |
userid | int | 客户主键 | |
username | text | 客户名称 | |
day | text | 日 | 记录下单日的时间,格式为 yyyyMMdd_yyyyMMdd 例如: 20220101_20220102 |
totalconsumption | double | 订单总金额 | 连续两天的订单总金额 |
totalorder | int | 订单总数 | 连续两天的订单总数 |
province_consumption_day_aggr
5、 根据dwd层表统计每个省每月下单的数量和下单的总金额,并按照year,month,region_id进行分组,按照total_amount降序排序,形成sequence值,将计算结果存入Hive的dws数据库province_consumption_day_aggr表中(表结构如下),然后使用hive cli根据订单总数、订单总金额、省份表主键均为降序排序,查询出前5条,在查询时对于订单总金额字段将其转为bigint类型(避免用科学计数法展示),将SQL语句与执行结果截图粘贴至对应报告中;
字段 | 类型 | 中文含义 | 备注 |
province_id | int | 省份表主键 | |
province_name | string | 省份名称 | |
region_id | int | 地区主键 | |
region_name | string | 地区名称 | |
total_amount | double | 订单总金额 | 当月订单总金额 |
total_count | int | 订单总数 | 当月订单总数 |
sequence | int | 次序 | |
year | int | 年 | 订单产生的年,为动态分区字段 |
month | int | 月 | 订单产生的月,为动态分区字段 |
provinceavgcmpregion
6、 请根据dws层表province_consumption_day_aggr计算出每个省份2020年4月的平均订单金额和该省所在地区平均订单金额相比较结果(“高/低/相同”),存入MySQL数据库shtd_result的provinceavgcmpregion表中(表结构如下),然后在Linux的MySQL命令行中根据省份表主键、省平均订单金额、地区平均订单金额均为降序排序,查询出前5条,将SQL语句复制粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下,将执行结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;
字段 | 类型 | 中文含义 | 备注 |
provinceid | int | 省份表主键 | |
provincename | text | 省份名称 | |
provinceavgconsumption | double | 该省平均订单金额 | |
regionid | int | 地区表主键 | |
regionname | text | 地区名称 | |
regionavgconsumption | double | 地区平均订单金额 | 该省所在地区平均订单金额 |
comparison | text | 比较结果 | 省平均订单金额和该省所在地区平均订单金额比较结果,值为:高/低/相同 |
regiontopthree
7、 根据dws层表来计算每个地区2020年订单金额前3省份,依次存入MySQL数据库shtd_result的regiontopthree表中(表结构如下),然后在Linux的MySQL命令行中根据地区表主键升序排序,查询出前5条,将SQL语句复制粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下,将执行结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;
字段 | 类型 | 中文含义 | 备注 |
regionid | int | 地区表主键 | |
regionname | text | 地区名称 | |
provinceids | text | 省份表主键 | 用,分割显示前三省份的id |
provincenames | text | 省份名称 | 用,分割显示前三省份的name |
provinceamount | text | 省份名称 | 用,分割显示前三省份的订单金额(需要去除小数部分,使用四舍五入) |
例如:
nationmedian
8、 请根据dwd层的相关表,计算出2020年每个省份所在地区的订单金额的中位数,存入MySQL数据库shtd_result的nationmedian表中(表结构如下),然后在Linux的MySQL命令行中根据地区表主键,省份表主键均为升序排序,查询出前5条,将SQL语句与执行结果截图粘贴至对应报告中。
提示:可用percentile函数求取中位数。
字段 | 类型 | 中文含义 | 备注 |
provinceid | int | 省份表主键 | |
provincename | text | 省份名称 | |
regionid | int | 地区表主键 | |
regionname | text | 地区名称 | |
provincemedian | double | 该省份中位数 | 该省份订单金额中位数 |
regionmedian | double | 该省所在地区中位数 | 该省所在地区订单金额中位数 |
省份累计订单量
9、 根据dwd层的数据,请计算每个省份累计订单量(订单信息表一条算一个记录),然后根据每个省份订单量从高到低排列,将结果打印到控制台(使用spark中的show算子,同时需要显示列名),将执行结果复制并粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;
例如:可以考虑首先生成类似的临时表A:
province_name | Amount(订单量) |
A省 | 10122 |
B省 | 301 |
C省 | 2333333 |
然后生成结果类似如下:其中C省销量最高,排在第一列,A省次之,以此类推。
C省 | A省 | B省 |
2333333 | 10122 | 301 |
提示:可用str_to_map函数减轻工作量