基于以下场景,使用SQL和Tableau完成项目要求
一家经营各种食品批发的批发商的业务正在扩张,面对日益增长的经营数据,他们希望更加直观便捷地了解公司运营情况。批发商提供了一组经营数据,要求你专注于其业务的一个维度,创建一个仪表板,提供与该维度相关的各种汇总统计信息。
选择下面的一个维度(viewpoint),提取相关数据制作一个仪表板(dashboard)展示可视化成果,探索有助于企业发展的任何洞见(insight);然后使用可视化创建一个演示文稿,报告有关该维度的摘要信息和你的洞见。
本项目的首要任务是为处于业务扩张阶段的食品批发商呈现运营动态,其主要经营活动是各类食品的进货与转售,通过低买高卖赚取收益,应当重点关注在售商品整体的销量情况,包括销售量与销售收入;同时,还应该关注各品类在售商品的销售变动情况,追踪市场需求,及时调整进货和销售策略。
为便于理解及提取数据,将所提供的项目数据绘制成如下所示的ER图。经营数据可分为商品和订单信息/供应商信息/客户信息/物流信息等部分,其中商品订单信息内容最为丰富,包括商品名称、种类、单价、运输规格、订单数量等信息;供应商和客户信息的数据结构类似,主要是联系方式与地理位置信息;物流信息主要是物流公司的联系方式、到货日期与出发/目的地信息,可以与客户和供应商信息相对照以确定商品的流向。另外,包含订单数据的orders表作为关键节点连接了其余各表,这一点在使用SQL提取数据时需要注意。
综合上述对业务的思考以及所提供的业务数据,本项目选择从产品角度切入,展示整体销售情况随时间变化的数据以及各类在售商品的销售变动情况。具体任务目标为:
导入数据
缺失值处理
一致化处理
异常值处理
创建视图
为便于提取所需数据,根据ER关系图将包含所需数据字段的表进行联结,以供后续调用。主要字段及代码如下:
字段名称 | 说明 |
---|---|
ProductName | 商品名称 |
CategoryName | 商品种类 |
sale_unit_price | 商品销售单价 |
Quantity | 商品销售数量 |
sales_income | 商品销售收入 |
-- 创建表联结视图
CREATE VIEW product_order AS (
SELECT
CS."CustomerID" AS CustomerID,
CS."CompanyName" AS CompanyName,
CS."City" AS City,
CS."Region" AS Region,
CS."Country" AS Country,
OD.orderid AS orderid,
OD.orderdate AS orderdate,
ODS."ProductID" AS ProductID,
ODS."UnitPrice" AS sale_unit_price,
ODS."Quantity" AS Quantity,
PD."ProductName" AS ProductName,
PD."UnitPrice" AS origin_unit_price,
round(CAST(ODS."Quantity"*ODS."UnitPrice" AS NUMERIC), 2) AS sales_income,
PD."UnitsInStock" AS UnitsInStock,
PD."UnitsOnOrder" AS UnitsOnOrder,
CG."CategoryName" AS CategoryName
FROM "Customers" AS CS
JOIN orders AS OD
ON OD.customerid = CS."CustomerID"
JOIN orderdetails AS ODS
ON OD.orderid = ODS."OrderID"
JOIN products AS PD
ON ODS."ProductID" = PD."ProductID"
JOIN "Categories" AS CG
ON CG."CategoryID" = PD."CategoryID"
);
提取整体销售数据
-- 按日期统计所有商品的销售数量总值与销售收入总额
SELECT
date_trunc('MONTH', CAST(OD.orderdate AS DATE)) AS od_date,
LEFT(OD.orderdate, 4) || '.' || SUBSTRING(OD.orderdate FROM 6 FOR 2) AS Date,
round(CAST(SUM(ODS."Quantity") AS NUMERIC), 2) AS total_Sales_num,
round(CAST(SUM(ODS."Quantity"*ODS."UnitPrice") AS NUMERIC), 2) AS total_Sales_Income
FROM orders AS OD
JOIN orderdetails AS ODS
ON OD.orderid = ODS."OrderID"
WHERE orderdate BETWEEN '2014-07-01' AND '2016-04-30'
GROUP BY 1, 2
ORDER BY 1;
按商品分类提取销售份额数据
-- 按商品分类统计销售收入占销售收入总额的比例
WITH TAB1 AS (
SELECT
"CategoryName" AS CategoryName,
SUM(sales_income) OVER (PARTITION BY ("CategoryName")) AS category_income,
SUM(sales_income) OVER () AS total_income
FROM product_order
WHERE orderdate BETWEEN '2014-07-01' AND '2016-04-30'
)
SELECT
categoryname,
round(CAST((category_income/total_income) AS NUMERIC), 4) AS percent
FROM TAB1
GROUP BY 1, 2
ORDER BY 2 DESC
;
按商品分类提取销售量和销售收入数据
-- 按商品分类统计销售量和销售收入,并按排名显示前N位商品的数据 (示例n=2)
SELECT
"CategoryName",
"ProductName",
SUM ( "Quantity" ) AS total_Sales_num,
SUM ( sales_income ) AS total_Sales_Income
FROM
product_order AS P_D
WHERE
orderdate BETWEEN '2014-07-01' AND '2016-04-30'
AND "CategoryName" IN (
SELECT -- get the category name of TOP2 revenue
"CategoryName" AS CategoryName
FROM
(
SELECT
"CategoryName",
SUM ( sales_income ) AS total_income
FROM
product_order AS P_D
WHERE
orderdate BETWEEN '2014-07-01' AND '2016-04-30'
GROUP BY
"CategoryName"
ORDER BY
total_income DESC
-- LIMIT 2
) AS top2rev
)
GROUP BY
"CategoryName",
"ProductName"
ORDER BY
total_Sales_num DESC;
根据上述提取的数据在tableau中制作仪表板,如下图所示。仪表板展示了2014年~2016年的经营情况,包括按月统计的商品销量总数和销售收入,各类商品销售收入的份额,以及按分类统计的商品销量和销售收入排名。
Tableau中默认将日期/时间字段作为分支结构处理,因此可以任意切换Total Quantity & Revenue图中的日期字段,选择按天/月/季度/年等不同粒度展现营收情况;右上角的Range of Order筛选器提供了类似Excel切片器/日程表的功能,可以通过拖动时间条以指定所展示的日期范围(作用于全局)。
左下角的Revenue by Category图表展示了各品类商品销售收入占总营收的百分比,而右下角的Quantity&Revenue by Category则利用颜色深度和条形长度分别体现了各类商品的销售收入与销售数量高低排名,通过视图内置的Category筛选器可以进一步地关注某类商品名下的子类销售细分情况。
根据拟定的目标,需要利用上述可视化结果从产品角度探索公司的经营状况。可以从整体的经营现状与发展趋势入手,了解营收构成,关注商品销售的变动情况,探究变动背后的可能影响因素。因此,提出以下问题:
整体销售情况
考虑到数据完整性,选取2014.07~2016.04的数据进行分析。
从整体上看,2014~2016年的商品销售数量和销售收入保持同步增长的趋势;从2015年下半年开始,销售收入增长明显;截至2016.04,销售收入达到了$134k,相较于期初的$30.2k翻了3倍。
各类商品的销售情况
公司主营商品包括8个大类共77项单品,覆盖了酒水饮料、乳制品、禽肉类、谷物、海产品、调味品、干果零食等领域。按商品大类看,整体营收构成较为均衡,酒水和乳制品是销售的主打产商品,分别贡献了21%和18.8%的收入。销量最大的单品是乳制品(Dairy Products)分类下的Camembert Pierrot ,而酒水(Beverages)分类下的Côte de Blaye 虽然销量仅为Camembert Pierrot的1/3,但却贡献了最高收入。
营收波动原因探究
对经营状况的分析可以从不同角度入手,其中之一就是经营状况的异常变动。注意到在2015~2016的销售收入增长阶段出现过一次明显的销售收入下降,有必要对其动因进行探究以预防此类不利情况的发生。
为了探究造成收入下降的原因,将此期间内各品类商品的销售收入变化情况以堆叠面积图的形式呈现,如下图所示。可以看到,在2015年11月,相较于其它品类,禽肉类商品(Meat/Poultry)的销售收入出现明显下滑。查阅具体数值可知,其销售收入由上个月的$14,730锐减至$1068,占11月份营收总额减少量的55%,因此初步判断11月收入下降的主要是由禽肉类商品的销售下滑引起的。
在仪表板中筛选出禽肉类商品及其子类的销售收入与销售数额进行观察,发现禽肉类商品11月份的销售量大幅下滑;将数据展开至单品层级,可以看出禽肉类商品的营收构成较为单一,排行前2名为Thüringer Rostbratwurst 与Alice mutton的单品贡献了接近70%的销售收入,尤其在2015年Q3之后,禽肉类商品的营收变动趋势与Thüringer Rostbratwurst单品保持高度一致。不难看出,11月销售收入下滑的主要原因是禽肉类商品销量下滑,特别是禽肉类单品Thüringer Rostbratwurst 的销量锐减。
为了预防此类情况,有必要进一步探究Thüringer Rostbratwurst 单品销量大幅下滑的原因;同时,应当采取措施优化禽肉类商品的营收构成,如寻求Thüringer Rostbratwurst的同类品牌加入商品清单,以降低单一的高价值商品销量/价格变动对营收的影响。
分析小结
本项目基于食品批发商提供的经营数据进行数据可视化与经营状况分析。从产品的销售情况角度出发,提取相关数据制作了仪表板以呈现随时间变化的商品整体销售收入与销售数量图像,并通过筛选器实现了各品类商品的销售份额与排名情况的可视化以及动态切换功能。在可视化的基础上对2014~2016年的经营状况进行了探究,评估了整体发展趋势,发现了2015年末营收大幅波动的现象并尝试分析其动因,给出了多样化配置商品种类以实现营收均衡的经营建议。
限于篇幅以及原数据提供的信息量,本项目仍有许多未完善之处,以下建议将有助于项目的改进与提升: