一道经典的sql面试题

今天讲解一道经典的sql面试题:
假设我们的数据是这个样子的:假设我们的表名称:sales

姓名(name)日期(day)每日销售金额(sal)
张三2016-01-01200.0
张三2016-01-03300.0
李四2016-01-02200.0
李四2016-01-04400.0
王五2016-01-05110.0
王五2016-01-06420.0
张三2016-02-01110.0
张三2016-02-03220.0
李四2016-02-02120.0
李四2016-02-04150.0
王五2016-02-05220.0
王五2016-02-06300.0
张三2016-03-01220.0
张三2016-03-03330.0
李四2016-03-02290.0
李四2016-03-04200.0
王五2016-03-05150.0
王五2016-03-06250.0

题目:使用一条sql按照月份统计出每个人在每个月的销售金额,以及在本月份的年度累计销售金额

我们希望得到如下的结果:

姓名月份本月销售金额年度累计销售金额
张三2016-01500.0500.0
张三2016-02330.0830.0
张三2016-03550.01380.0
李四2016-01600.0600.0
李四2016-02270.0870.0
李四2016-03490.01360.0
王五2016-01530.0530.0
王五2016-02520.01050.0
王五2016-03400.01450.0

解题
1.截取日期到月
这里我是创建了一个视图:

create view sales_view 
as
select name,substr(DATE_FORMAT(day,'%Y-%m-%d'),1,7) as mon,sal from sales ;

在视图:sales_view中的数据也就变成了

姓名(name)月份(mon)每日销售金额(sal)
张三2016-01200.0
张三2016-01300.0
李四2016-01200.0
李四2016-01400.0
王五2016-01110.0
王五2016-01420.0
张三2016-02110.0
张三2016-02220.0
李四2016-02120.0
李四2016-02150.0
王五2016-02220.0
王五2016-02300.0
张三2016-03220.0
张三2016-03330.0
李四2016-03290.0
李四2016-03200.0
王五2016-03150.0
王五2016-03250.0

2.统计每个人每个月的销售情况

排序:按照每个人,每个月
统计每月的销售总额

sql:

select name,mon,sum(sal) as sum_sal  from sales_view group by name,mon;

3.自己和自己join,约束条件是name
sql:

select * from (
(select name,mon,sum(sal) as sum_sal  from sales_view group by name,mon) l
inner join 
(select name,mon,sum(sal) as sum_sal  from sales_view group by name,mon) r
on 
l.name=r.name)

根据笛卡尔积表特性:
张三 1月份 【销售额】 将会对应到N个月的张三的销售额
如图:
这里写图片描述

这样我们计算累计金额的时候,就可以group by r.name,r.mon首先按照姓名排序,sum(l.sum_sal),同时添加一个where条件:l.mon<=r.mon
4.得到累计销售金额
sql:

select *,sum(l.sum_sal) from (
(select name,mon,sum(sal) as sum_sal  from sales_view group by name,mon) l
inner join 
(select name,mon,sum(sal) as sum_sal  from sales_view group by name,mon) r
on 
l.name=r.name)
where l.mon<=r.mon
group by r.name,r.mon

至此,你会惊奇的发现右侧的结果就是答案
这里写图片描述

最终的sql

select r.*,sum(l.sum_sal) from (
(select name,mon,sum(sal) as sum_sal  from sales_view group by name,mon) l
inner join 
(select name,mon,sum(sal) as sum_sal  from sales_view group by name,mon) r
on 
l.name=r.name)
where l.mon<=r.mon
group by r.name,r.mon
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值