数据分析小白实录(二)

    有志同道合的朋友,欢迎我们一起学习,互相帮助我的微信是tss2817411628. 

    这是我的一次学习数据分的项目实战,我在开始之前只掌握mysql的基本语句,然后就没看讲解视频直接自己按照问题写sql,结果废了很大功夫也没搞懂,所以我把这次六道题做一次总结,把我的代码发出来,老师的也发出俩,梳理两种代码的思路。自娱自乐,如果对你有帮助,不胜荣幸;如果你是前辈能指出我的问题,劳驾指出问题,我一定不胜感激!!!

    咱们开始~

    先看下表都有啥:

第一张表,订单信息。

第二张,顾客信息表


 userinfo  用户信息表

涉及表:

  orderinfo  订单详情表        userinfo  用户信息表

    | orderid  订单id                 | userid    用户id

    | userid    用户id                 | sex        用户性别

    | isPaid    是否支付             | birth      用户出生日期

    | price    付款价格

    | paidTime  付款时间

问题:1、统计不同月份的下单人数


            2、统计用户三月份的回购率和复购率


            3、统计男女用户消费频次是否有差异


            4、统计多次消费的用户,第一次和最后一次消费间隔是多少天

            5、统计不同年龄段,用户的消费金额是否有差异

            6、统计消费的二八法则,消费的top20%用户,贡献了多少消费额

1、统计不同月份的下单人数

我的代码:

先按照月份进行分组,然后就可以统计订单数量了,注意同一用户可能会产生多个订单,所以要去重

select MONTH(paidTime),COUNT(DISTINCT userid) from orderinfo 

WHERE paidTime<>'0000-00-00 00:00:00' AND isPaid ='已支付'

GROUP BY MONTH(paidTime) ;


老师代码

select year(paidTime), month(paidTime), count(distinct userid) as cons 

from orderinfo 

where isPaid="已支付"and paidTime<>'0000-00-00 00:00:00' 

group by year(paidTime),month(paidTime);

老师的代码先过滤掉未支付和支付时间的脏数据,然后按照年月分组,在对年月分组中的客户进行去重聚合

错误代码

这是我写的一个错误代码

SELECT MONTH,COUNT(userid) as '订单人数'

FROM(

select *,MONTH(paidTime) as month

from orderinfo 

WHERE paidTime<>'0000-00-00 00:00:00' AND isPaid='已支付'

GROUP BY userid)a

GROUP BY MONTH;

代码结果显示3月份是对得上号,但是四月五月不对,为啥呢?

因为我的子查询是对用户进行聚合,如果a用户3月份消费且在四月也消费,那么分组时候只显示他在3月份的消费,四月份就不显示出来,那么最外面的select自然也统计不上了。比如说这个id=18347的客户

2、统计用户三月份的回购率和复购率

回购率:上月购买用户中有多少用户本月又再次购买

我的代码

SELECT COUNT(DISTINCT userid)/(

                SELECT count(DISTINCT userid)

                FROM orderinfo

                WHERE isPaid="已支付" AND MONTH(paidTime)=3)#这里是3月份消费人数


FROM orderinfo

WHERE userid IN(

                                SELECT  DISTINCT userid

                                FROM orderinfo

                                WHERE isPaid="已支付" AND MONTH(paidTime)=3)#这里是3月份消费的用户名单

AND isPaid="已支付" AND MONTH(paidTime)=4;#3月份消费的用户名单知道了,带进去4月份取比对,会选出3月份和4月份都消费的用户


最后用3月和4月都消费的人数和除以三月份消费人数(我觉得我的代码太长了,而且感觉笨笨的,能有人指点就好了)

老师的代码


#1、每个用户,每月的消费

#2、两个表联结,通过userid和b表的时间偏移(往前偏一个月)来联结

#3、然后在按月份分组前提下,汇总左边总次数和右边有次数,求回购率

SELECT MONTH(atime),COUNT(*),COUNT(userid2),COUNT(userid2)/COUNT(*) as huigou

FROM(

SELECT *

FROM( #1、每个用户,每月的消费

SELECT userid,DATE_FORMAT(paidTime,'%Y-%m-%01') as atime

FROM orderinfo

WHERE isPaid <>'未支付' AND paidTime <>'0000-00-00 00:00:00'

GROUP BY userid,atime)a

LEFT JOIN (

SELECT userid as userid2,DATE_FORMAT(paidTime,'%Y-%m-%01') as time

FROM orderinfo

WHERE isPaid <>'未支付' AND paidTime <>'0000-00-00 00:00:00'

GROUP BY userid2,time)b

ON  a.userid=b.userid2 AND atime=DATE_SUB(time,INTERVAL 1 MONTH)

#2、两个表联结,通过userid和b表的时间偏移(往前偏一个月)来联结

)c

GROUP BY atime;#3、然后在按月份分组前提下,汇总左边总次数和右边有次数,求回购率



#复购率:

#3月份的消费情况,显示每个用户的消费次数

SELECT *,COUNT(userid)

FROM orderinfo

WHERE isPaid ='已支付' AND MONTH(paidTime)=3

GROUP BY userid; #三月每个用户的购买情况以及次数


#用消费1次以上的用户除以消费总数

SELECT MONTH(paidTime),

SUM(IF(cs>1,1,0)),#如果买的次数大于1,记1

COUNT(cs),SUM(IF(cs>1,1,0))/COUNT(cs) as fugou 

FROM(

SELECT *,COUNT(userid) as cs

FROM orderinfo

WHERE isPaid ='已支付' AND MONTH(paidTime)=3

GROUP BY userid

)a; #用上一条结果作为表


老师的代码

select

  count(1) as userid_cons,

  sum(if(cons>1,1,0)) as fugou_cons,

  sum(if(cons>1,1,0))/count(1) as fugou_rate

from (select

        userid,

        count(1) as cons

      from orderinfo

      where isPaid="已支付"

      and month(paidTime)="03"

      group by userid

  ) a;


3、统计男女用户消费频次是否有差异

我的代码

SELECT COUNT(*),

            SUM(IF(sex='男',1,0)) AS '男性购买数量',

            SUM(IF(sex='女',1,0)) AS '女性购买数量',

            SUM(IF(sex='男',1,0))/COUNT(*) AS '男生购买率',

            SUM(IF(sex='女',1,0))/COUNT(*) AS '女生购买流率'

FROM(

                SELECT a.userid,sex

                FROM orderinfo AS a

                INNER JOIN userinfo AS b ON a.userid=b.userid

                WHERE isPaid <>'未支付' AND  sex <>'' 

                GROUP BY a.userid   ##筛选出每个用户消费记录

)c;


我求的是男和女生的 占比


老师的代码

select

  sex,

  avg(cons) as avg_cons

from (select

  a.userid,

  sex,

  count(1) as cons

from orderinfo a

inner join (select * from userinfo where sex<>'') b

on a.userid=b.userid

group by a.userid,sex) a

group by sex;


老师求的是男女生购买的平均数


4、统计多次消费的用户,第一次和最后一次消费间隔是多少天

我的代码

SELECT      userid,

                    MIN(paidTime),

                    MAX(paidTime),

                    DATEDIFF(MAX(paidTime),MIN(paidTime))

FROM orderinfo

WHERE isPaid <>'未支付'#筛选出有效支付记录

GROUP BY userid HAVING COUNT(userid)>1;#过滤掉消费一次的用户


老师的代码


select

  userid,

  min(paidTime),

  max(paidTime),

  datediff(max(paidTime), min(paidTime))

from orderinfo

where isPaid="已支付"

group by userid

having count(1)>1;

我和老师的代码差不多

5、统计不同年龄段,用户的消费金额是否有差异

#通过计算各年龄段人数,然后求各年龄段消费金额,然后求平均消费金额

#计算每个人年龄,然后根据userid聚合orderinfo

#筛掉脏数据并且对用户进行分组,同时计算每个用户的消费总金额!!!!(这个点卡了我好久)

#然后将上步结果作为子查询,计算各年龄段消费金额

SELECT age,avg(prices)'每个年龄段平均消费金额',AVG(ci)'每个年龄段平均消费次数'

FROM(

SELECT a.userid,SUM(price) as prices,COUNT(a.userid) AS ci,age#要在这里进行聚合每个用户的消费金额

FROM(

SELECT *,CEIL(TIMESTAMPDIFF(YEAR,birth,NOW())/10) as age

FROM userinfo

WHERE birth>'1901-00-00'

)a

INNER JOIN orderinfo AS b

ON a.userid=b.userid

WHERE isPaid<>'未支付'

GROUP BY a.userid

)c

GROUP BY age;


老师的代码

select

  age,

  avg(cons),

  avg(prices)

from (select

  a.userid,

  age,

  count(1) as cons,

  sum(price) as prices

from orderinfo a

inner join (select

  userid,

  birth,

  now(),

  ceil(timestampdiff(year,birth,now())/10) as age

from userinfo

where birth>'1901-00-00') b

on a.userid=b.userid

group by a.userid,age) a

group by age;

老师代码的结果和我有点细小差别,但总体不影响


6、统计消费的二八法则,消费的top20%用户,贡献了多少消费额


最后一题老师都是分开算的比较简单

我的代码

SELECT SUM(zj)/(

SELECT SUM(zzj)

FROM(

SELECT *,SUM(price) AS zj

FROM orderinfo

WHERE isPaid<>'未支付'

GROUP BY userid

ORDER BY SUM(price) DESC

)b

)

FROM(

SELECT *,SUM(price) AS zj

FROM orderinfo

WHERE isPaid<>'未支付'

GROUP BY userid

ORDER BY SUM(price) DESC

LIMIT 17000)a


老师的代码

1、统计每个用户的消费金额,并进行一个降序排序

select

  userid,

  sum(price) as total_price

from orderinfo a

where isPaid="已支付"

group by userid;

2、统计一下一共有多少用户,以及总消费金额是多少

select

  count(1) as cons,

  sum(total_price) as all_price

from (select

  userid,

  sum(price) as total_price

from orderinfo a

where isPaid="已支付"

group by userid) a;

3、取出前20%的用户进行金额统计

select

  count(1) as cons,

  sum(total_price) as all_price

from (

select

  userid,

  sum(price) as total_price

from orderinfo a

where isPaid="已支付"

group by userid

order by total_price desc

limit 17000) b ;

        项目一前前后后一共做了三遍,三遍才能能掌握的比较透。每个题目我错在哪里,或者思路哪里不对,也学到了许多细节。很累,才开始也很难,尤其之前课程代码都非常简单,自己第一次独立做题,突然觉得好难,难得进行不下去,但是还是硬着头皮做,如今6道终于全部吃透,雨过天晴的感觉真好。

下面我罗列一下,我在这6道题中的一点收获。可能不对,抱着怀疑态度看吧。

取别名

在select 后面可以取别名,但是在参与筛选时候不可以使用别名。

比如你计算总消费金额 sum(price) as zj,如果后面用where筛选,只能写sum(price)>***,写sum(zj)>***,就会报错

有子查询的注意事项



做子查询时候的表中不能有命名相同的列

不然会报1060 - Duplicate column name 'userid'的错误

前路漫漫,继续加油

你可能感兴趣的:(数据分析小白实录(二))