本文是对Adventure Works案例的一个总结,记录了整个项目需求分析与实现的过程,主要任务是使用Hive SQL完成ETL过程,并且连接到PowerBI实现可视化,最终将整个分析成果展示出来。再分析2020年11月的销售情况,并以PPT的形式展现。
本次项目的成果:

一、项目背景

Adventure Works Cycle是国内一家制造公司,该公司生产和销售金属和复合材料自行车在全国各个市场。销售方式主要有线上零售和线下批发或零售。

  • 产品介绍
    这家公司主要有下面四个产品线:
    Adventure Works Cycles生产的自行车;
    自行车部件,例如车轮,踏板或制动组件;
    从供应商处购买的自行车服装,用于转售给Adventure Works Cycles的客户;
    从供应商处购买的自行车配件,用于转售给Adventure Works Cycles的客户。

二、项目需求

随着线上业务的开展,需要增强公司数据化方面的治理,让前线的业务同学能够实现自主分析,从而能实现对市场的快速判断。因此,要求数据部门和业务部门沟通需求的自主分析的数据指标,从而实现可视化看板。
业务需求:查看最新的销量,销售额趋势以及商品的销售占比;获取当天,前一天,当月,当季,当年的各区域各城市销量和销售额,以及同比数据;对热销产品进行展示。

三、分析过程

1.需求分析

要想实现业务人员的自主分析,需满足以下两点:

  • 具有可视化的操作页面,方便直观分析
  • 数据每日自动化更新
    PowerBI可以实现用户的可视化操作,把相关的表聚合后连接到PowerBI做数据的可视化展示即可,但是聚合的表示固定的,需要将聚合表的操作部署到linux服务器上定时运行,从而实现每日更新数据。
    分析流程如下:

2.mysql数据源中观察数据

根据业务需求,梳理出三张要用到的表:

3.搭建指标体系

指标维度:
时间维度:今日、昨日、当月、当季、当年

地域维度:销售大区、省份、城市

产品维度:产品类别、产品占比、热销产品

经过分析需要聚合的3张数据表:
1)dw_order_by_day 每日环比表:

本表是对当日数据的一个汇总聚合,通过聚合“create_date”字段,获得当日总销量、总销售金额、并计算出客单价。计算每日销售金额与前日金额环比。通过“create_date”字段关联dim_date_df(日期维度表),方便后续对日、月、季度、年等时间维度的销售情况进行聚合展示。

2)dw_customer_order 时间地区产品聚合表:
提取当日维度下ods_sales_orders(订单明细表)和ods_customer(每日新增用户表),并通过“customer_key”字段关联两张表。提取订单主键、订单日期、客户编号、产品名、产品子类、产品类别、产品单价、所在区域、所在省份、所在城市这些字段,使用groupby方法对订单日期、产品名、产品子类、产品类别、所在区域、所在省份、所在城市的逐级聚合。获得相应的单总量、客户总量和销售总金额。

3)dw_amount_diff 当日维度表:
提取生成的的dw_order_by_day(每日环比表)的数据。通过“is_today”、“is_yesterday”、“is_current_year”、“is_last_year”等这些字段中的值:1和0来判断时间。对当日、昨日、月、季度、年等的销售金额,销售量和客单价聚合起来,完成同比计算。使用“amount”、“order“、”avg“标记销售金额,销售量和客单价的同比结果。

四. 聚合表的实现过程

1. Sqoop抽取mysql数据到hive数据库

通过sqoop工具将日期维度表、每日新增用户表、订单明细表将数据从mysql中抽取到hive数据库的ods层,通常将代码写在shell脚本上,在linux 系统中运行即可。
下面是部分shell脚本代码(sqoop_dim_date_df.sh),将日期维度表的内容提取到hive中:

hive -e "drop table if exists ods.dim_date_df" # 删除hive原有的旧表
sqoop import \
--hive-import \
## 告诉jdbc,连接mysql的url
--connect jdbc:mysql://IP:3306/adventure_ods \
--username ##### \      ## 连接mysql的用户名
--password ##### \   ## 连接mysql的密码
--query \  ## 构建表达式<sql语句 >执行
"select * from dim_date_df where "'$CONDITIONS'" " \ ##注意:必须要加上where"$CONDITIONS", 否则报错
--fetch-size 50000 \  ## 一次从数据库读取 n 个实例,即n条数据
--hive-table ods.dim_date_df \ ## 创建dim_date_df表(默认也会自动创建表)
--hive-drop-import-delims \  ## 在导入数据到hive时,去掉数据中的\r\n\013\010这样的字符
--delete-target-dir \  ## 如果目标文件已存在就把它删除
--target-dir /user/hadoop/sqoop/dim_date_df \
-m 1  ## 迁移过程使用1个map(开启一个线程)

sqoop_ods_sales_orders.sh、sqoop_ods_customer.sh与上述方式相同,这里不再赘述。

2. 在hive数据库中做数据聚合表

编写hive sql从hive数据仓库ods层的日期维度表、每日新增用户表、订单明细表中读取数据进行聚合,完成dw_order_by_day 每日环比表、dw_customer_order 时间地区产品聚合表、dw_amount_diff 当日维度表的聚合操作。

聚合每日环比表(create_dw_order_by_day.sh)脚本:

#!/bin/shhive -v -e "
drop table if exists ods.dw_order_by_day;  ## 删除原有的旧表CREATE TABLE ods.dw_order_by_day(    ## 创建表结构create_date string,is_current_year bigint,is_last_year bigint,is_yesterday bigint,is_today bigint,is_current_month bigint,is_current_quarter bigint,sum_amount double,sum_order bigint);## 这里的插入语句,因为做聚合需要关联多张表做聚合,这里使用with查询来提高查询性能
with dim_date as
(select create_date,is_current_year,is_last_year,is_yesterday,is_today,is_current_month,is_current_quarterfrom ods.dim_date_df),
sum_day as
(select create_date,sum(unit_price) as sum_amount,count(customer_key) as sum_orderfrom ods.ods_sales_ordersgroup by create_date)insert into ods.dw_order_by_dayselect b.create_date,b.is_current_year,b.is_last_year,b.is_yesterday,b.is_today,b.is_current_month,b.is_current_quarter,a.sum_amount,a.sum_order
from sum_day as a
inner join dim_date as b
on a.create_date=b.create_date;

聚合时间地区产品聚合表(create_customer_order.sh) 脚本:

#!/bin/bashhive -v -e "
use ods;drop table if exists dw_customer_order;CREATE TABLE dw_customer_order(create_date string,product_name string,cpzl_zw string,cplb_zw string,order_num bigint,customer_num bigint,sum_amount double,is_current_year bigint,is_last_year bigint,is_yesterday bigint,is_today bigint,is_current_month bigint,is_current_quarter bigint,chinese_province string,chinese_city string,chinese_province_city string,chinese_territory string);drop table sales_customer1;
create table sales_customer1 as
select b.create_date,b.chinese_province,b.chinese_city ,b.chinese_province_city ,b.chinese_territory,a.unit_price,a.sales_order_key,a.customer_key,a.english_product_name,a.cpzl_zw,a.cplb_zw
from ods_customer as b
inner join ods_sales_orders as  a
on a.customer_key=b.customer_key;drop table sales_customer;
create table sales_customer as
select create_date,chinese_province,chinese_city ,chinese_province_city ,chinese_territory,sum(unit_price) as sum_amount,count(sales_order_key) as order_num,count(distinct customer_key) as customer_num ,english_product_name,cpzl_zw,cplb_zw
from sales_customer1
group by create_date,cpzl_zw,cplb_zw,english_product_name,chinese_province,chinese_city ,chinese_province_city,chinese_territory;with dim_date as
(select create_date,is_current_year,is_last_year,is_yesterday,is_today,is_current_month,is_current_quarterfrom ods.dim_date_df) insert into dw_customer_orderselect b.create_date,a.english_product_name as product_name,a.cpzl_zw,a.cplb_zw,a.order_num,a.customer_num,a.sum_amount,b.is_current_year,b.is_last_year,b.is_yesterday,b.is_today,b.is_current_month,b.is_current_quarter,a.chinese_province,a.chinese_city ,a.chinese_province_city ,a.chinese_territoryfrom sales_customer as a inner join dim_date as bon  a.create_date=b.create_date;drop table sales_customer;
drop table sales_customer1;
"

聚合当日维度表(create_amount_diff.sh) 脚本:

#!/bin/shhive -v -e "
drop table if exists ods.dw_amount_diff;CREATE TABLE ods.dw_amount_diff(category string,d_amount   double,d_order    double,d_avg      double);with dw_order as
(select
*,
add_months(from_unixtime(unix_timestamp(create_date, 'yyyy-MM-dd'), 'yyyy-MM-dd'), -12) as before_lastyear_date
from ods.dw_order_by_day),
select dw_order_by_day as(
select * from ods.dw_order_by_day)
insert into ods.dw_amount_diffselectt.category,t.d_amount,t.d_order,t.d_avgfrom(
select
'day' as category,
((sum(a.sum_amount)/sum(b.sum_amount))-1) as d_amount,
((sum(a.sum_order)/sum(b.sum_order))-1) as d_order,
((sum(a.sum_amount) / sum(a.sum_order))/ (sum(b.sum_amount) /sum(b.sum_order)) -1) as d_avg
from
(select * from dw_order where is_today=1) a
left join dw_order_by_day b
on a.before_lastyear_date = b.create_date
union all
select
'yesterday' as category,
((sum(a.sum_amount)/sum(b.sum_amount))-1) as d_amount,
((sum(a.sum_order)/sum(b.sum_order))-1) as d_order,
((sum(a.sum_amount) / sum(a.sum_order))/ (sum(b.sum_amount) /sum(b.sum_order)) -1) as d_avg
from
(select * from dw_order where is_yesterday=1) a
left join dw_order_by_day b
on a.before_lastyear_date = b.create_date
union all
select
'month' as category,
((sum(a.sum_amount)/sum(b.sum_amount))-1) as d_amount,
((sum(a.sum_order)/sum(b.sum_order))-1) as d_order,
((sum(a.sum_amount) / sum(a.sum_order))/ (sum(b.sum_amount) /sum(b.sum_order)) -1) as d_avg
from
(select * from dw_order where is_current_month=1) a
left join dw_order_by_day b
on a.before_lastyear_date = b.create_date
union all
select
'quarter' as category,
((sum(a.sum_amount)/sum(b.sum_amount))-1) as d_amount,
((sum(a.sum_order)/sum(b.sum_order))-1) as d_order,
((sum(a.sum_amount) / sum(a.sum_order))/ (sum(b.sum_amount) /sum(b.sum_order)) -1) as d_avg
from
(select * from dw_order where is_current_quarter=1) a
left join dw_order_by_day b
on a.before_lastyear_date = b.create_date
union all
select
'year' as category,
((sum(a.sum_amount)/sum(b.sum_amount))-1) as d_amount,
((sum(a.sum_order)/sum(b.sum_order))-1) as d_order,
((sum(a.sum_amount) / sum(a.sum_order))/ (sum(b.sum_amount) /sum(b.sum_order)) -1) as d_avg
from
(select * from dw_order where is_current_year=1) a
left join dw_order_by_day b
on a.before_lastyear_date = b.create_date) t;
"

聚合之后数据仓库ods层中的表数据如下:

3. Sqoop导出聚合表到mysql

Sqoop export 导出:将数据从Hadoop(如hive等)导入关系型数据库当中。
注意:在我们导出数据到mysql前,我们必须要确保表在mysql中已经创建好了,sqoop 底层并不会帮我们创建表。

  • 在mysql中先创建dw_order_by_day:
CREATE TABLE `hive_dw_order_by_day` (`create_date` date DEFAULT NULL,`is_current_year` int(11) DEFAULT NULL,`is_last_year` int(11) DEFAULT NULL,`is_yesterday` int(11) DEFAULT NULL,`is_today` int(11) DEFAULT NULL,`is_current_month` int(11) DEFAULT NULL,`is_current_quarter` int(11) DEFAULT NULL,`sum_amount` double DEFAULT NULL,`sum_order` bigint(20) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
  • 将每日环比表导出到mysql中(export_dw_order_by_day.sh)脚本:

!/bin/bashsqoop export \
--connect jdbc:mysql://IP:3306/adventure_dw\
--username ##### \
--password ##### \
--table hive_dw_order_by_day \
--export-dir /user/hive/warehouse/ods.db/dw_order_by_day \
--input-null-string "\\\\N" \
--input-null-non-string "\\\\N"  \
--input-fields-terminated-by "\001"  \
--input-lines-terminated-by "\\n"  \
--columns  create_date,is_current_year,is_last_year,is_yesterday,is_today,is_current_month,is_current_quarter,sum_amount,sum_order \  ## 选择列并控制它们的排序
-m 1

export_dw_customer_order.sh和export_dw_amount_diff.sh与上述方式相同,这里不再赘述。

4.在linux服务器上做定时部署

利用服务器,每日6时左右自动执行代码,完成表的聚合工作,实现数据自动化更新。
linux内置的cron进程能帮我们实现定时任务, cron是一个linux下的定时执行工具,可以在无需人工干预的情况下运行作业。
(1)编写schedule.sh文件,按照执行顺序添加文件:

#!/bin/bash
sh /home/adventure/sqoop_dim_date_df.sh
sh /home/adventure/sqoop_ods_sales_orders.sh
sh /home/adventure/sqoop_ods_customer.shsh /home/adventure/create_dw_order_by_day.sh
sh /home/adventure/create_customer_order.sh
sh /home/adventure/create_amount_diff.shsh /home/adventure/export_dw_order_by_day.sh
sh /home/adventure/export_dw_customer_order.sh
sh /home/adventure/export_dw_amount_diff.sh

(2)添加定时任务,设定每天早上6点执行任务
编辑crontab文件,vi /etc/crontab

# For details see man 4 crontabs# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed
0 6 * * * root /home/adventure/schedule.sh

五. PowerBI部署展示

可视化报表一共有三页:主页、时间趋势图、区域分布图。

  • 主页展示内容:
    1.销售指标:销售金额、订单量、客单价以及同比去年的数据;
    2.从时间维度分析销售情况(今日、昨日、月、季度、年维度);
    3.销售排名前十的产品;
    4.各个品类订单量占比情况;
    5.各个省份销量情况;
    6.区域、城市的切片器。
  • 时间趋势图展示内容:
    展示近14天的销量完成情况、销量趋势图和销售金额趋势图。
  • 区域分布图展示内容:
    1.各区域的销售金额、销量、客户数情况;
    2.各城市的销售金额、销量、客户数情况;
    3.各区域销售金额占比情况;
    4.各个省份销售金额排行;
    5.时间、区域、城市、产品的切片器。

adventure项目案例分析相关推荐

  1. python在工程管理专业的应用案例_Python课程中实际项目案例分析

    项目三 内容推荐系统 传统的需求收集方式多是做一些调研,如用户访谈.问卷调查.焦点小组.现场调研等.虽说这是直面用户很好的方式,但是也存在一些局限性, 如样本不够多,投入时间人力成本大,访谈环境对受访 ...

  2. linux thinkphp 计划任务_ThinkPHP定时任务项目案例分析

    定时任务常见的是Linux中的crontab定时任务,这种是通过编写脚本来执行的,它会在后台一直循环执行.但是有时候我们没有服务器权限或者说我们没有独立的服务器,那又该怎么办?其实,定时任务还有一种就 ...

  3. c mysql项目案例_C语言项目案例分析 目录

    目录 第1篇  实用工具篇 第1章  万年历(TC 2.0实现) 自学视频.源程序: 配套资源\mr\1\ 2 1.1  万年历概述 3 1.1.1  功能概述 3 1.1.2  万年历效果预览 3 ...

  4. 科研院所网管开发项目案例分析

    1.电力科学研究院 1.1.项目背景 中国电力科学研究院,是国家电网公司直属科研单位,是中国电力行业多学科.综合性的科研机构. 电力科学院在承建电力核心骨干网--光芯片网络系统中,需要开发管理光芯片网 ...

  5. Android动画了解—一些项目案例分析

    文章目录 写在前面 带路径运动的过渡动画 整体缩放的效果 整体宽高改变的过渡效果 两个界面布局的过渡效果 带水波纹布局的效果 几行代码实现转圈圈的效果 界面翻转的效果 写在前面 最近听说MIUI 12 ...

  6. 【渝粤教育】广东开放大学 文化产业项目案例分析 形成性考核 (51)

    选择题 题目:<武林外传>发生在虚拟的唐代. 答案:看左侧 题目:<武林外传>中李大嘴是一个厨师. 答案:看左侧 题目:<疯狂动物城>是一部动画片. 答案:看左侧 ...

  7. C语言项目案例分析 源代码

    用C语言编写的"日历表"源代码 "日历"结构 /*日历 *1.显示当前时间 *2.输入并验证输入的内容是否正确,如果错误重新输入             输入函 ...

  8. 联想ERP项目实施案例分析(大结局):回到最初再反思IT价值

    由于昨天被盗号(我昨天上午都在医院看牙医),被坏人给大家群发了广告,幸亏昨天中午回来发现问题及时报告微信客服中心,加强安全防护,账号又被追了回来.在此继续警醒各位朋友,安全这个事,平时不出问题看不出来 ...

  9. 软件架构最佳实践和案例分析

    软件架构是软件业的一个重要研究领域,正受到越来越多的关注,其地位也日益明显地体现出来.而架构设计师--也就成为软件系统的最高设计者.此课程就是为有志成为卓越架构师的人准备的培训课程.作为架构设计师,需 ...

  10. 2022年版中国氢能行业投资前景预测与项目规划分析报告

    2022年版中国氢能行业投资前景预测与项目规划分析报告 ═━┈┈━══━┈┈━══━┈┈━══━ [报告编号]:  415330 [出版时间]:  2022年3月 [出版机构]:  中商经济研究网 第 ...

最新文章

  1. “稳定”凸包----poj1228
  2. JAVA_OA管理系统(四)番外篇:使用Spring注解注入属性
  3. Java 11即将发布的功能–启动单文件源程序
  4. C#LeetCode刷题之#53-最大子序和(Maximum Subarray)
  5. Java Jvm虚拟机的内存模型概述 《对Java的分析总结》(一)
  6. 如何运行vue项目 ?(详解,建议收藏) ❤️
  7. 八类网线和七类网线的区别_Cat8 八类网线与超五类网线、六类网线、超六类网线及七类/超七类网线的区别...
  8. windows下安装Pytorch环境
  9. 孔浩javascript笔记三
  10. laravel下载安装
  11. Fedora 9安装vmware tools解决方案
  12. 衡量系统性能常见指标
  13. 如何用opencv(C++)读入sar.tif图(复数矩阵)(radasat2)
  14. 达人评测 联想YOGA Duet 2021
  15. 双十一自动领喵币工具
  16. SpringMVC里的Model、Map、ModelMap以及ModelAndView
  17. 安卓分屏模式的简单适配
  18. 算法工程师当前选哪个方向好?| 文末送书
  19. GitHub疯狂转发!阿里巴巴彩版java性能调优实战,终于到手了!文末福利
  20. java判断文件路径的状况

热门文章

  1. SQL 嵌套 N 层太长太难写怎么办?
  2. 洛谷 P1653 猴子 解题报告
  3. EDA学习1.3之开关的封装
  4. Element UI 之 Tabs 栏下拉菜单的实现
  5. 跳楼机[DP+spfa]
  6. 都在说CI/CD,到底什么是CI/CD
  7. cdrom是什么意思_开启电脑时出现CDROM是什么意思
  8. 正定矩阵、二次型与椭圆椭球
  9. 什么是Usenet | 第2部分
  10. 魔兽争霸lostTemple地图