mysql基本操作题视频_mysql视频练习题

mysql视频练习题

2个表:

order_info_utf.csv

user_info_utf.csv

导入到mysql数据库。

题目:

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

⚠️这里的人数是指共有多少名自然人下单,不是指“人次”。所以count()内加上distinct,去重复。

SELECT month(paidTime), count(distinct userId) FROMtest1.orderinfowhere isPaid ="已支付"group by month(paidTime);

+-----------------+------------------------+

| month(paidTime) | count(distinct userId) |

+-----------------+------------------------+

| 3 | 54799 |

| 4 | 43967 |

| 5 | 6 |

+-----------------+------------------------+

3 rows in set (1.23 sec)

2.统计用户3月的回购率和复购率

2.1复购率:本月消费1次以上的人数/本月消费的总人数。

SELECT userid, count(userid) as ct FROMtest1.orderinfowhere isPaid ="已支付"and month(paidTime) = 3

group by userid having ct > 1;

得到一个列表:本月消费1次以上的人的id和他的消费次数的集合。

这里使用了having筛选出消费1次以上的人的id。

更好的方法是,查询结果显示2个列,分别储存“本月消费1次以上的人数”, “本月消费的总人数”:

所以,需要外面再加一层,并去掉having:

select count(if(ct > 1, 1, null)), count(1) from(SELECT userid, count(userid) as ct FROMtest1.orderinfowhere isPaid ="已支付"and month(paidTime) = 3

group by userid) as t

得到2个数字16916和54799,所以复购率是:30.87%

2.2回购率:3月消费的人,又在4月进行了消费。这是一次回购:x。x除以3月消费的人数= 3月回购率。

3月消费的人数: 54799人

select count(1) from(select userid fromtest1.orderinfowhere isPaid ="已支付"and month(paidTime) = 3

group by userid) as user

3月消费的人,又在4月进行了消费的人数: 13119人

select count(1) from(select userid fromtest1.orderinfowhere isPaid ="已支付"and month(paidTime) = 3

group by userid) asuser_3inner join(select userid fromtest1.orderinfowhere isPaid ="已支付"and month(paidTime) = 4

group by userid) asuser_4on user_3.userid = user_4.userid;

因此最后: 13119/54799 =23.94%, 所以3月回购率是23.94%。

2.3计算所有月份的回购率

需要对2.2的代码进行修改。

select * from(select userid, date_format(paidTime, "%Y-%m-01") as m, count(isPaid) fromtest1.orderinfowhere isPaid ="已支付"group by userid, m)) asaleft join(select userid, date_format(paidTime, "%Y-%m-01") as m, count(isPaid) fromtest1.orderinfowhere isPaid ="已支付"group by userid, m) asbon a.userid = b.userid

809607a215a46d7d0ed7c40bf46f7267.png

上面的代码把两个完全相同的表连接,解释:

1.子查询使用userid和date_format(paidTime, "%Y-%m-01")列进行分组。即得到的记录是用户在一个月内的消费次数。

2.使用date_format()函数,改变格式,把日设为01,以便进行后面的DATE_SUB(start_date,INTERVALexprunit)计算。

然后,见完整代码:

3.⚠️使用的是左连接left join

4.因为使用左连接,所以可以这么增加一个筛选条件:and a.m = date_sub(b.m, interval 1 month)

即让a的月份=b的月份-1.   这样就可以把:每条记录按照同一用户在3月消费记录和4月消费记录连接起来,同样4月和5月,6月和7月等等,即相邻月份进行关联,以便计算回购率。

不符合条件的b表的value都是null表示。

5. 最后的外层表用a.m进行分组,然后使用聚合函数统计a表每个月的消费人数,以及b.表每个月的消费人数。因为通过条件合并了相邻月份。所以最后得到回购率的分母和分子。

select a.m, count(a.m),count(b.m) from(select userid, date_format(paidTime, "%Y-%m-01") as m, count(isPaid) fromtest1.orderinfowhere isPaid ="已支付"group by userid, m) asaleft join(select userid, date_format(paidTime, "%Y-%m-01") as m, count(isPaid) fromtest1.orderinfowhere isPaid ="已支付"group by userid, m) asbon a.userid =b.useridand a.m = date_sub(b.m, interval 1 month)group by a.m

4020fcdd01d0a4b8f55b1676ae75b7dd.png

⚠️

6. 这里必须使用and,而不是where,

因为where是对left join ...on..后的数据再筛选,不符合条件的就被去掉了。

而and是在 on子句的内部,不符合条件的数据会用null表示。

and a.m = date_sub(b.m, interval 1 month)

3.统计男女的消费频次是否有差异

设所有男性消费者为x, 所有男性消费者的合计消费次数是x_order,那么男性消费频次为 x_order/x

select sex, avg(ct) from(select o.userid, t.sex, count(1) as ct from orderinfo asoinner join(SELECT * FROMtest1.userinfowhere sex <>"") ton o.userid = t.userid and o.ispaid ="已支付"group byo.userid, t.sex) t2group by sex

5f08433316a70c61df18c7497c3c3e1d.png

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

(相当于一个消费者的消费的周期)

首先,查询每个用户第一次消费和最后一次消费的时间,使用max, min函数:

SELECT userid, max(paidtime), min(paidtime) FROMtest1.orderinfowhere ispaid ="已支付"group byuseridhaving count(1) > 1

然后,让max()减去min()但得到的是秒,所以需要使用datediff()函数,

SELECT userid,max(paidtime), min(paidtime), datediff(max(paidtime), min(paidtime)) as interval_day FROMtest1.orderinfowhere ispaid ="已支付"group by userid having count(1) > 1

97e3d6cc9e8534aedc14fe64c3e3b25a.png

最后,再加上一层:

select avg(df) from(SELECT userid,max(paidtime), min(paidtime), datediff(max(paidtime), min(paidtime)) as df FROMtest1.orderinfowhere ispaid ="已支付"group byuseridhaving count(1) > 1) t

得到一个结果:15.6484天。

求平均值,这是不准确的简单计算。根据用户类型,个别高消费频次用户,应该属于统计中的极值,不当算在统计样本中。

或者改求中位数的值。

5统计不同年龄段,用户的消费金额是否有差异?(将消费金额定义为每个年龄段的人均消费金额和总金额。)

首先,得到一个每个用户所在年龄组的表t1

然后,使用orderinfo,得到每个用户的消费总额的表t2。

最后,把t1,t2内连接后,按照age_group分组,并使用聚合函数avg()计算每个年龄组的人均消费金额。

select t1.age_group, cast(avg(t2.price) as decimal(10,2)) as avg_price from(select userid, ceil((year(now())-year(birth))/10) as age_group fromuserinfowhere birth > '1901-01-01') t1              #用'1901-01-01'去除一些脏数据inner join(SELECT userid, sum(price) as price FROMtest1.orderinfowhere isPaid = '已支付'

group byuserid) t2on t1.userid =t2.useridgroup by t1.age_group order byage_group

更好的方法是使用case when:

select t1.age_group, cast(avg(t2.price) as decimal(10,2)) as avg_price from(selectuserid,case

when (year(now())-year(birth)) <=10 then "<=10"when (year(now())-year(birth)) between 11 and 20 then "10 to 20"when (year(now())-year(birth)) between 21 and 30 then "20 to 30"when (year(now())-year(birth)) between 31 and 40 then "30 to 40"when (year(now())-year(birth)) between 41 and 50 then "40 to 50"when (year(now())-year(birth)) between 51 and 70 then "50 to 70"when (year(now())-year(birth)) >=71 then ">=71"end asage_groupfromuserinfowhere birth > '1901-01-01') t1inner join(SELECT userid, sum(price) as price FROMtest1.orderinfowhere isPaid = '已支付'

group byuserid) t2on t1.userid =t2.useridgroup by t1.age_group order by t1.age_group

结果:

+-----------+-----------+

| age_group | avg_price |

+-----------+-----------+

| 10 to 20 | 846.63 |

| 20 to 30 | 1003.96 |

| 30 to 40 | 1178.61 |

| 40 to 50 | 1183.59 |

| 50 to 70 | 1099.86 |

| <=10 | 1322.29 |

| >=71 | 3269.92 |

+-----------+-----------+

6统计消费的2/8法则,消费的top20%的用户,贡献了多少额度

首先,计算出每个用户的消费额度@total, 和总共有多少消费用户。

然后,计算前20%的用户数量,使用limit得到这个用户范围的表格t

最后,对t计算消费总额@top20_price,这个数值除以@total,得到0.85。即前20%的用户,贡献了85%的额度。

select @count := count(userid), @total := sum(price) as total from(SELECT userid, sum(price) as price FROMtest1.orderinfowhere isPaid = '已支付'

group byuseridorder by price desc) t; #total 318503081.54, count = 85649

select @top20_percent := ceil(@count*0.2); #17130

select @top20_price :=sum(t.price) from(SELECT userid, sum(price) as price FROMtest1.orderinfowhere isPaid = '已支付'

group byuseridorder by price desclimit17130) t # 272203711.45

select @top20_price/@total; #0.85

或者:

select @count := count(userid), @total := sum(price) as total from(SELECT userid, sum(price) as price FROMtest1.orderinfowhere isPaid = '已支付'

group byuseridorder by price desc) t; #total 318503081.54, count = 85649

--

select @top20_percent := ceil(@count*0.2); #17130

select sum(price)/@total from(selectrow_number()over(order by price desc ) asrk,

userid, pricefrom(SELECT userid, sum(price) as price FROMtest1.orderinfowhere isPaid = '已支付'

group byuseridorder by price desc) ast1

)ast2where t2.rk < @top20_percent

这里使用row_numbe()计算函数,得到一个排名,然后用where子句得到前20%的用户的表t2,最后t2进行计算。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值