某电商在线奶粉销量数据分析-SQL+Tableau自动化分析

2023-11-09

本文数据集来源:Baby Goods Info Data

数据库:MySQL

数据库管理软件:DataGrip

可视化分析软件:Tableau

本文sql文件、可视化分析源文件地址:DataScience

文章目录

数据预处理与导入

导入数据到数据库

  1. 创建Trade表

create table trade
(
	user_id varchar(20) not null comment '用户id',
	auction_id varchar(20) not null comment '购买行为编号',
	cat_id varchar(20) null comment '商品所属的大类下的子类',
	cat1 varchar(15) null comment '商品所属的大类',
	property text null comment '商品属性',
	buy_mount int null comment '购买数量',
	day varchar(8) null comment '购买日期'
);

  1. 使用DataGrip将(sample)sam_tianchi_mum_baby_trade_history.csv导入trade表

  2. 创建babyinfo表

create table babyinfo
(
	user_id varchar(20) not null,
	birthday varchar(8) null,
	gender char null
);
  1. 使用DataGrip将(sample)sam_tianchi_mum_baby.csv导入babyinfo表

  2. 然后再在DataGrip修改日期数据的数据格式为date格式

    • 定义表格时,直接使用date格式,导入会出现错误

image-20210306103624042

数据探索:

Trade表

  • buy_mount (购买数量/销量)
  • user_id(用户id)
  • auction_id(购买行为编号)
  • cat1(商品所属的大类)
  • cat_id(cat1的子类,是更细分的类别)
  • property(商品属性)
  • day(购买时间)

统计缺失值信息

select
       sum(user_id is null)
       ,sum(auction_id is null)
       ,sum(cat1 is null)
       ,sum(cat_id is null)
       ,sum(trade.property is null)
       ,sum(trade.buy_mount is null)
       ,sum(trade.day is null)
from trade;

image-20210306140439252

  • 只有144条记录的商品属性property有缺失

用户数量:

select
       count(user_id)
      ,count(distinct user_id)
from trade;

image-20210306135312997

  • 29971条购买记录中,却有29944个用户,说明只有不到30个用户购买超过两次,说明奶粉类产品的复购率不是很高。

统计不同购买数量的用户

select
buy_num
,count(user_id) as user_num
from
(
    select
    user_id
    ,count(user_id) as buy_num
    from trade
    group by user_id
    )as tem
group by buy_num
order by user_num;

image-20210306135810577

  • 99.92%的用户都只购买了一次

商品类别

select
       cat1,
       count(distinct cat_id) as 子类数量
from trade
group by cat1
order by 子类数量;

image-20210306140913368

  • 总共有六个大类,每个大类下面分别由数量不一的子类构成

每次购买数量

select
       buy_mount 每次购买数量
       ,count(user_id) 消费次数
from trade
group by buy_mount
order by 消费次数;

image-20210306141313583

时间跨度

select max(day),
       min(day)
from trade;

image-20210306141735258

  • 可以看到销售数据从2012年7月开始,到2015年2月结束,其中2015年2月只有5天的数据,数据不完整,在下面的聚类运算中,统计量会比较小

babyinfo表

  • user_id(用户id)
  • birthday(出生日期)
  • gender:性别(0 男孩,1 女孩,2性别不明)

缺失值统计

select sum(user_id is null),
       sum(birthday is null),
       sum(gender is null)
from babyinfo;

image-20210306141552756

有信息的用户数量

select count(distinct user_id) -- 有信息的用户数量
from babyinfo;

image-20210306142024848

  • 虽然只有3.2%的用户有详细的婴儿年龄等信息,但是考虑到数据抽样的随机性,仍能反映出整体分布的一些规律信息

不同性别婴儿的数量

select gender, -- 不同性别的数量
       count(gender)
from babyinfo
group by gender;

image-20210306142212503

探索分析

销量信息

按天统计每天的销量和活跃的用户数量

  1. sql查询语句
select day,
       sum(buy_mount) as 销量,
       count(distinct user_id) as 用户数量
from mytest.trade
group by day
order by day
  1. 使用tableau进行可视化

image-20210306144616679

image-20210306152825851

  • 从图中可以看到,在部分日期的销量和用户数量是平时数据几千倍,可能会有异常,需要进行查明
  1. 查询销量异常记录:
-- 查询单次购买超过100的记录数
select user_id,day,
       buy_mount
from trade
where buy_mount>100
order by buy_mount desc;

image-20210306154150299

  • 从结果中可以看到,有不少用户的一次购买量超过了100罐,甚至有一次购买10000罐的,很有可能是批发商购买或者是刷单行为,需要对这些记录进行筛选剔除

经调查:

图片

婴幼儿在0-1岁时,理论上一共需要81罐400g奶粉,假设用户除“双十一”、“618”外其他时间每次只购买1罐,那么两个购物节平均需要承担27罐奶粉,向上取整后,以单笔销量超过30罐奶粉作异常值处理

  1. 更改连接sql语句,剔除异常销量数据,重新查询后,销量用户数量图如下:
select day,
       sum(buy_mount) as 销量,
       count(distinct user_id) as 用户数量
from mytest.trade
where buy_mount < 30
group by day
order by day

image-20210306160925720

  • 1 从销量图上可以看出,每年的销量高峰是双十一和双十二购物期间

  • 2 在春节期间,销量出现了明显的低谷

  • 3 购物节的销量呈现逐年增加的趋势

观察销量在一周内的变化

-- 分析按星期的销量,用户量
select dayname(day) as D,
       sum(buy_num) as 销量,
       sum(user_num) as 活跃用户量
from
    (
        select
            day,
            sum(buy_mount ) as buy_num,
            count(distinct user_id) as user_num
        from trade
        where buy_mount<30
        group by day
        ) as tem
group by D,dayofweek(day)
order by dayofweek(day) ;

image-20210306165341236

image-20210306165253735

  • 可以看到周六日的销量和活跃用户数量都明显小于工作日,很有可能是部分父母在周末需要带孩子,而在工作日进行购买奶粉

分析按月购买的情况:

-- 分析按月购买的情况
select
       月份,
       max(if(年份 = 2012,buy_num,0)) as 2012年,
       max(if(年份 = 2013,buy_num,0)) as 2013年,
       max(if(年份 = 2014,buy_num,0)) as 2014年,
       max(if(年份 = 2015,buy_num,0)) as 2015年
from
    (
        select
        month(day) as 月份,
        year(day) as 年份,
        sum(buy_mount ) as buy_num,
        count(distinct user_id) as user_num
        from trade
        where buy_mount<30
        group by year(day), month(day)
        ) as tem
group by 月份
order by 月份;

image-20210306193127461

image-20210306194049989

image-20210308094050563

  • 在每年中,销量主要呈现出两个大的周期
    • 周期1:2-5月销量上升,5-7月销量下降
    • 周期2:7-11月销量上升,11-2月份销量下降
  • 主要可能影响因素:
    • 1 不同月份新生儿数量不同
    • 2 不同月份的促销力度不同
  • 每年的1,2月份的销量数据相对都比较低,可能是受到春节的影响,在后面需要对春节前后的销量进行细致分析,来采取2015年2月中后期的销售决策

2015年春节前后销量详细分析

  • 2013年春节:2月9日-2月15日
  • 2014年春节:1月30日-2月6日
  • 2015年春节:2月19日-2月25日
  • 当前的数据只截至到了2015年2月5日(腊月十七)
  • 可以通过调用往年腊月的销售数据,来辅助2015年腊月的销售决策

通过筛选器,观察每年腊月初一到腊月十五的销售额

image-20210308095838186

  • 可以看到,2015年的腊月初一到十五的销量虽然仍然很大,但是相比于去年的同比增速,今年的增速有所下降

往年腊月的销售额与同比增速

image-20210308100203882

  • 截至目前2015年2月5日(据春节还有14天),已完成销量已经超过了去年的腊月销量,但是要想超过去年的增长率,仍然有1029✖(1.7741)-1129= 696罐的销售额需要完成,平均每天需要完成696/14=49.7罐的销售目标。

观察2014年和2015年腊月初一到腊月十五各产品大类的销量与同比增速

image-20210308102149676

  • 观察可知,只有28大类的销售同比增速超过了去年,38大类产品增速基本与去年平均增速持平,二其他大类的增速都比较低于预期,需要详细分析营销策略。

腊月每天的销量变化

image-20210308103144075

image-20210308103210389

  • 可以看到,腊月十五过后,销量会逐渐下降,因此需要在接下来1-2周内,马上采取一定的促销活动,来保证本月的销售量达到或超过去年的同比增速。

对比每月新出生人数:

  • 数据生成参考婴儿信息一节

image-20210308092557616

  • 通过与上图比较可以看出,5月份的销量高峰,很可能是受到8月份出生人数增加的影响,父母为了提前准备,从而提前购买了奶粉
  • 11月的销量高峰,是受到打折促销的影响

销量与季度

image-20210306194336988

  • 每年都是第一季度的销量最少(春节影响),第二、第三季度销量中等,第四季度销量最高(打折促销,为过年囤货)。

产品类别分析

每个大类奶粉的购买情况

-- 每个大类奶粉的购买情况
select
       cat1 as 类别,
        sum(buy_mount) as 销量,
       count(distinct user_id) as 用户数
from trade
where buy_mount<30
group by cat1
order by cat1;

image-20210306194906782

image-20210308104804634

  • 50008168、28、50014815都是销量比较大的产品类别,相比而言,其他类别的销量比较少

image-20210306202707056

  • 销量排名基本与用户数量相同,除了38产品,虽然销量排名第四,但是用户量却比较少,可能是用户单次购买量较大,或者店家的满减促销做的比较好,需要进一步调查。

找到热销的子类信息

-- 寻找热销子类(销量前十或用户数量前十)
select
tem1.*,
用户量排名, 用户量
from
         (select cat_id,
                 @j := @j + 1 as 销量排名,
                 销量
          from (select @j := 0) as t,
               (
                   select cat_id,
                          sum(buy_mount) as 销量
                   from trade
                   where buy_mount < 30
                   group by cat_id
                   order by sum(buy_mount) desc) as n
         ) as tem1

join
         (select cat_id,
                 @i := @i + 1 as 用户量排名,
                 用户量
          from (select @i := 0) as t,
               (
                   select cat_id,
                          count(distinct user_id ) as 用户量
                   from trade
                   where buy_mount < 30
                   group by cat_id
                   order by count(distinct user_id ) desc) as m
         ) as tem2
on tem1.cat_id = tem2.cat_id
where 销量排名<10 or 用户量排名<10;

image-20210306212311935

image-20210306212752835

  • 可以看到,销量比较高的奶粉子类的销量,都基本上都在逐年增加,其中50010558的销量增长迅速,可以在今年进行优先推广。

image-20210306214246003

  • 通过tableau可以清晰地查看不同子类销售量的变化趋势,从而采取不同的措施,来提高销量

婴儿阶段分析

  • 1段:0-6个月(4-6月已可食用辅食)
  • 2段:6-12个月(6月大:可食用糊状或泥状的食物;9月大:可食用有硬度食物)
  • 3段:1-3岁
  • 4段:3-7岁(已经符合入读公办幼儿园的年龄,此阶段奶类流质食物已经不是主流)
-- 创建年龄段信息视图
create view mytest.age_info as
(
    select
    b.user_id,
       cat1,
       cat_id,
       buy_mount,
       day as buy_day,
       birthday,
       (
           case
            when datediff(day,birthday)/30<0 then '未出生'
            when datediff(day,birthday)/30<6 then '0-6个月'
            when datediff(day,birthday)/365<1 then '6-12个月'
           when datediff(day,birthday)/365<3 then '1-3岁'
           when datediff(day,birthday)/365<7 then '3-7岁'
           else '大于七岁'
           end
        ) as 年龄分段,
       if((floor(((to_days(`t`.`day`) - to_days(`b`.`birthday`)) / 365)) < 0), '未出生',
          floor(((to_days(`t`.`day`) - to_days(`b`.`birthday`)) / 365))) AS `年龄`,
       (
           case gender
           when 0 then '男'
           when 1 then '女'
           else '不明'
           end
        ) as 性别
from babyinfo b
join trade t
    on b.user_id = t.user_id
where t.buy_mount<30
    );

image-20210307102833623

每个年龄段的婴儿数量和购买量:

-- 每个年龄段的人数和购买量:
select
        年龄分段,
       count(distinct user_id) as 人数,
       sum(buy_mount) as 购买总量
from age_info
group by 年龄分段
order by field(年龄分段,'未出生','0-6个月','6-12个月','1-3岁','3-7岁','大于七岁');

image-20210307103744142

image-20210307103857678

  • 1.在整个食用奶粉的各个阶段中,1-3岁对奶粉的需求量最大
  • 2.可以看到,有相当一部分家长,购买奶粉都是在孩子出生前购买的,可以考虑针对这种提前购买的行为,有针对性地展开销售

各年龄购买情况

image-20210307105130727

  • 可以看到,0-1岁的用户量和奶粉销量都最高,随着年龄的上升,婴儿逐渐能够食用其他食物,奶粉需求逐渐下降

产品用户画像

不同产品大类的用户群体分布

image-20210307131342804

不同用户的产品购买比例

image-20210308132401293

不同产品子类的用户群体分布

image-20210307131645021

复购情况分析

创建复购用户的视图

create view mytest.multi_info
as
    (
select
       user_id,
       cat_id,
       cat1,
       buy_mount,
       day
from trade
where
      user_id in
(
    select
    user_id
    from trade
    where buy_mount<30
    group by user_id
    having count(auction_id)>1
)
order by  user_id,day);

计算复购率

-- 计算复购率
select
a.num1/count(distinct user_id) as 复购率
from
       (select count(distinct user_id) as num1 from multi_info) as a ,
     trade b;

image-20210307152836103

查询有重复购买行为用户复购的是否是同一小类的奶粉

-- 查询有重复购买行为用户复购的是否是同一小类的奶粉
select
       t.num as 复购产品种类数,
       count(user_id) as 用户数
from
    (select
    user_id,count(distinct cat_id) as num
    from multi_info
    group by user_id) as t
group by t.num;

image-20210307152240900

查询有重复购买行为用户复购的是否是同一大类的奶粉

-- 查询有重复购买行为用户复购的是否是同一大类的奶粉
select
       t.num as 复购产品种类数,
       count(user_id) as 用户数
from
    (select
    user_id,count(distinct cat1) as num
    from multi_info
    group by user_id) as t
group by t.num;

image-20210307152333811

分析结果汇总

销售趋势分析

image-20210308195734657

  • 可以看到每年的销售高峰在双十一,双十二两个高峰,其他时间销售量变化比较平稳
  • 销售量呈现逐年增加的趋势,并且增速逐年增加
  • 每年的春节期间,会出现销量低谷

春节销量低谷分析

image-20210308212347538

  • 截至目前2015年2月5日(据春节还有14天),已完成销量已经超过了去年的腊月销量,但是要想超过去年的增长率,仍然有1029✖(1.7741)-1129= 696罐的销售额需要完成,平均每天需要完成696/14=49.7罐的销售目标。
  • 只有28大类的销售同比增速超过了去年,38大类产品增速基本与去年平均增速持平,二其他大类的增速都比较低于预期,需要详细分析营销策略。
  • 腊月十五之后,销量就会逐渐下降,因此需要在接下来一周内,采取营销措施,来刺激销量,从而达到去年的增长率

销售周期性分析

image-20210308212417560

  • 在每年中,销量主要呈现出两个大的周期
    • 周期1:2-5月销量上升,5-7月销量下降
    • 周期2:7-11月销量上升,11-2月份销量下降
  • 可以看到周六日的销量和活跃用户数量都明显小于工作日,很有可能是部分父母在周末需要带孩子,而在工作日进行购买奶粉
  • 5月份的销量高峰,很可能是受到8月份出生人数增加的影响,父母为了提前准备,从而提前购买了奶粉

不同类别产品销量占比分析

image-20210308212647934

各年龄段销售差异

image-20210308212727343

参考资料:

1只会环比下降3%的数据分析师还有救吗?

2电商婴儿用品数据分析(SQL)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

某电商在线奶粉销量数据分析-SQL+Tableau自动化分析 的相关文章

  • ASP SQL Server 连接

  • MySQL:如何获取每个分组的x个结果数[重复]

    这个问题在这里已经有答案了 可能的重复 mysql 在 GROUP BY 中使用 LIMIT 来获取每组 N 个结果 https stackoverflow com questions 2129693 mysql using limit w
  • hive sql查找最新记录

    该表是 create table test id string name string age string modified string 像这样的数据 id name age modifed 1 a 10 2011 11 11 11 1
  • SQL Server 2008 错误 233

    我正在使用以下 sql 脚本在 SQL Server 2008 中创建新登录名 CREATE LOGIN xyz WITH PASSWORD xyz DEFAULT DATABASE master DEFAULT LANGUAGE us e
  • 包含列和行总计的 SQL 数据透视表

    我正在尝试将行和列总计添加到该数据透视表中 create table test4 city nvarchar 10 race nvarchar 30 sex nvarchar 10 age int insert into test4 val
  • 选择多列 按一列分组 按计数排序

    我在Oracle中有以下数据集 c1 c2 c3 1A2 cat black 1G2 dog red B11 frog green 1G2 girl red 试图得到以下结果 基本上我首先尝试获取具有重复 c1 的行 c1 c2 c3 1G
  • 带有可变 WHERE 子句的批量 UPDATE 表

    我有一堆值对 foo1 bar1 foo2 bar2 我想做一堆更新 将 foo 列设置为 foo1 其中 bar 列为 bar1 我正在使用 psycopg2 在 Python 中执行此操作 我可以executemany与查询UPDATE
  • Snowflake 中的动态 SQL

    当我在雪花中运行动态 SQL 时 遇到以下错误 未完成对 SQL MAIN 的分配 因为值超出了变量的大小限制 它的大小是263 限制为 256 内部存储大小以字节为单位 这是代码 SET v G 1 SET v G1 v G VARCHA
  • 3 个表的 SQL 查询(或联接)

    第一次在 Stack Overflow 上问问题 很棒的资源 但是只有一件事真正让我作为 SQL 新手感到困惑 我有三个表 我想获取与鲍勃的学生相关的所有导师的姓名 表 1 教师 ID Name 1 Bob 表 2 学生 STUDENT I
  • H2 SQL 日期比较

    在 H2 数据库中 如何在 TIMESTAMP 类型的列上运行查询 SELECT FROM RECORDS WHERE TRAN DATE lt 2012 07 24 Try 2012 07 24
  • SQL 使用另一列的键和最大值设置列

    我需要根据同一 ID 的 duration 列的最大值更新 max register 列 将值设置为 1 其他值设置为 0 初始表 Id duration max register 1 0 0 1 7 0 1 3 0 2 10 0 2 5
  • 如何使用原始 SQL 查询实现搜索功能

    我正在创建一个由 CS50 的网络系列指导的应用程序 这要求我仅使用原始 SQL 查询而不是 ORM 我正在尝试创建一个搜索功能 用户可以在其中查找存储在数据库中的书籍列表 我希望他们能够查询 书籍 表中的 ISBN 标题 作者列 目前 它
  • 使用来自另一个数据库的选择查询更新 mysql 表

    我有两个数据库 我想用另一个数据库表中的值更新一个表 我正在使用以下查询 但它不起作用 UPDATE database1 table1 SET field2 database2 table1 field2 WHERE database1 t
  • ORA-12728: 正则表达式中的范围无效

    我想检查表中是否插入了有效的电话号码 所以我的触发代码在这里 select start index into mob index from gmarg mobile operators where START INDEX substr ne
  • SQL查询查找具有特定数量关联的行

    使用 Postgres 我有一个架构conversations and conversationUsers Each conversation有很多conversationUsers 我希望能够找到具有确切指定数量的对话conversati
  • 处理与不同相关实体的一对多的正确模式

    我有一个 C 项目 我使用实体框架作为 ORM 我有一个User 可以向多家银行付款 每家银行都是一个独立的实体 并且每家银行都由不同的字段描述 问题是 一User可以没有或有很多不同的Banks 我不太确定如何对此进行建模 临时解决方案是
  • 是否可以从子查询中获取多个值?

    有没有办法让子查询在oracle db中返回多列 我知道这个特定的sql会导致错误 但它很好地总结了我想要的 select a x select b y b z from b where b v a v from a 我想要这样的结果 a
  • 具有不同组合的产品和产品包的数据库模型

    您将如何设计数据库来实现此功能 考虑一个场景 我们想要创建一个产品关系 封装 假设我们创建一个产品表 prod id prod name prod fee 1 prepaid A 19 usd 2 prepaid B 29 usd 3 pr
  • 需要在 SQL Server 中透视字符串值

    我有一个包含值的表 描述为 Occupation String Name String Developer A Developer B Designer X Coder Y Coder Z 我需要数据透视格式的值 Designer Deve
  • 多边形内的 SQL 地理点在 STIntersect 上不返回 true(但使用 Geometry 返回 true)

    我不想仅仅为了在 STIntersect 中返回 true 而将地理数据转换为几何图形 下面是 SQL 中的代码 DECLARE point GEOGRAPHY GEOGRAPHY Point 1 1 4326 DECLARE polygo

随机推荐