前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >金融行业项目:你每月消费多少?

金融行业项目:你每月消费多少?

原创
作者头像
猴子数据分析
修改2020-11-26 11:37:38
1K0
修改2020-11-26 11:37:38
举报
文章被收录于专栏:猴子数据分析猴子数据分析

某理财银行有下面3个表。

交易表记录了每天交易的客户交易时间、客户号、消费类型和消费金额。其中,交易类型有两种值:消费和转账。

客户表记录了客户信息,包括客户号,客户名称和客户所属的银行分行号。

分行号记录每个分行的信息,包括分行号、分行名称及对应上级分行。

该理财银行要求对客户及销售额分析报告,要求如下:

1.计算2016年1-3月的消费总金额,生成如下格式的查询结果

2.提取2016年3月消费金额大于等于1288的客户名单,并给出这些客户信息

3.汇总各省分行(省分行下属支行也需要汇总至省分行)的2016年3月的总消费金额

【解题步骤】

观察三张数据表看出交易表和客户表通过“客户号”关联,客户表和银行分行对应表通过“分行号”有关联。

1.计算2016年1-3月的消费总金额,并以月份作为列名的格式显示

1)交易表中的交易类型有两种(消费和转账),所以要对交易类型=消费 进行筛选。同时,要分析的是2016年的数据,所以也要对交易时间筛选。

代码语言:javascript
复制
1 select *
2 from 交易表
3 where 交易类型 = "消费" and year(交易时间) = 2016;

2)对交易时间按格式分类(year(),month()),用case when 语句对交易时间进行判断,符合2016年1-3月的记录并显示金额,不符合显示空值。

代码语言:javascript
复制
1 select     (case when year(交易时间) = 2016 and month(交易时间) = 1
2                  then 交易金额 else null end) as 2016年1月,
3            (case when year(交易时间) = 2016 and month(交易时间) = 2
4                  then 交易金额 else null end) as 2016年2月,
5            (case when year(交易时间) = 2016 and month(交易时间) = 3
6                  then 交易金额 else null end) as 2016年3月
7  from 交易表;

查询结果如下

3)符合记录的交易金额求和,得出1-3月份总的消费额

代码语言:javascript
复制
1 select
2      sum(case when year(交易时间) = 2016 and month(交易时间) = 1
3               then 交易金额 else null end) as 2016年1月,
4      sum(case when year(交易时间) = 2016 and month(交易时间) = 2
5               then 交易金额 else null end) as 2016年2月,
6      sum(case when year(交易时间) = 2016 and month(交易时间) = 3
7               then 交易金额 else null end) as 2016年3月
8 from 交易表
9               where 交易类型 = "消费" and year(交易时间) = 2016;

查询结果如下

2.提取2016年3月消费金额大于等于1288的客户名单,并显示这些列客户名称,2016年3月总消费金额,2016年3月首次达到1288的时间

该如何得出这两列呢?

1)2016年3月总消费金额

"客户名称“在客户表,交易金额在交易表中,涉及到2个表,所以要用到多表联结。

代码语言:javascript
复制
1 select a.客户名称,b.*
2 from 客户表 as a
3  inner join 交易表 as b
4 on a.客户号 = b.交易客户;

2016年3月总消费金额:先找出2016年3月份的消费数据 ,然后分析每个客户的总消费金额。

筛选交易时间为2016年3月的记录(between * and *),同时交易类似是消费。

代码语言:javascript
复制
1 select a.客户名称,b.*
2 from 客户表 as a
3 inner join 交易表 as b
4  on a.客户号 = b.交易客户
5 where b.交易时间 between "2016-03-01" and "2016-03-31"
6       and b.交易类型 = "消费";

每个客户的交易金额,涉及到“每个”就要想到《猴子 从零学会SQL》里讲过的“分组汇总”来解决。

按交易客户分组(group by),汇总交易金额(求和sum)。

代码语言:javascript
复制
1 select a.客户名称,
2        sum(b.交易金额) as 2016年3月总消费金额
3 from 客户表 as a
4  inner join 交易表 as b
5  on a.客户号 = b.交易客户
6 where b.交易时间 between "2016-03-01" and "2016-03-31"
7       and b.交易类型 = "消费"
8 group by a.客户名称;

查询结果如下

2)2016年3月首次达到1288的时间

通过交易表对每个客户的交易金额逐条累计求和,找出最接近交易金额大于或者等于1288的记录。例如下图是交易客户1的累加:

第1行的累计消费金额为第一条消费金额12.5

第2行的累计薪水为雇员第一条消费金额+第二条消费金额12.5+200之和

依次类推...

如何计算出每行的累计薪水?

累计求和问题要想到《猴子 从零学会SQL》里讲过的窗口函数,语法如下。

代码语言:javascript
复制
1 <窗口函数> over (partition by <用于分组的列名>
2                               order by <用于排序的列名>)

用聚合函数作为窗口函数,有累计的功能。因为本题是累计“求和”,所以用聚合函数sum。

代码语言:javascript
复制
1 select 交易客户,交易时间,
2       sum(交易金额) over (partition by 交易客户
3                           order by 交易时间) as "累计消费金额"
4 from 交易表
5 where 交易时间 between "2016-03-01"
6  and "2016-03-31"and 交易类型 = "消费";

查询结果如下

将上诉查询结果记录为表c,筛选累计消费金额大于1288的记录

代码语言:javascript
复制
1 select *
2  from  c
3 where 累计消费金额>1288;

查询结果如下:

那么如何获得每个客户累计消费金额最先到达1288的记录呢?这时可以按照客户分组,对交易时间进行排序(窗口函数 row_number)

代码语言:javascript
复制
1 select * ,
2       row_number() over(partition by 交易客户
3                          order by 交易时间) as 排序
4 from  c
5 where 累计消费金额>1288;

查询结果如下:

观察得到,每个客户的第一条记录,即累计金额最接近1288的记录和交易时间。

将上诉查询结果记为表d,筛选第一条记录就是。

代码语言:javascript
复制
1 select *
2 from d
3 where 排序=1;

查询结果如下

3)将上诉查询结果记为表e(每个客户首次累计消费达到1288),通过“交易客户”和客户表联结,就可以得到分析要求的客户名称、客户2016年3月首次达到1288的时间

代码语言:javascript
复制
1 select  a.客户名称,e.交易时间 as 2016年3月首次达到1288的时间
2 from 客户表 a inner join e
3 on a.客户号 = e.交易客户;

将前面的步骤一,步骤二整合在一起,得出客户名称,2016年3月总消费金额,2016年首次达到1288时间的三个字段

代码语言:javascript
复制
1 select a.客户名称,
2       sum(b.交易金额) as 2016年3月总消费金额, 
3      e.交易时间 as 2016年3月首次达到1288的时间
4 from 客户表 a
5   inner join 交易表 b
6 on a.客户号 = b.交易客户
7 inner join 
8  (
9       select *
10          from 
11         (
12           select * ,
13                  row_number()over partition by 交易客户
14                                     order by 交易时间) as 排序
15              from
16                ( 
17                select 交易客户,交易时间,
18                       sum(交易金额) over (partition by 交易客户 
19                                             order by 交易时间) as "累计消费
20 金额" 
21                  from 交易表
22                 where 交易时间 between "2016-03-01" and "2016-03-31"
23                   and 交易类型 = "消费"
24                   ) as c where 累计消费金额>1288
25                  ) as d  where 排序=1
26                ) as e 
27    on a.客户号 = e.交易客户
28  where b.交易时间
29    between  "2016-03-01" and "2016-03-31" 
30   and b.交易类型="消费"
  group by  a.客户名称;

查询结果如下

3.汇总各省分行(省分行下属支行也需要汇总至省分行)的2016年3月的总消费金额

得出每个分行2016年3月的消费总金额:通过客户表找到每个客户的所属分行,汇总每个分行的消费金额;

得出每个省行的消费总金额:再通过银行分行对应表找到每个分行对应的上级分行,得出对应省行的总消费金额

1)得出每个分行2016年3月的消费总金额

因为涉及到3张表的字段,需要3张表联结

代码语言:javascript
复制
1 select * 
2 from交易表 as a
3 inner join 客户表 as b 
4 on a.交易客户 = b.客户号
5 inner join 银行分行对应表 as c
6  on b.所属分行 = c.分行号;

筛选出2016年3月份的消费数据

代码语言:javascript
复制
1 select * 
2 from交易表 as a
3 inner join 客户表 as b
4  on a.交易客户 = b.客户号
5 inner join 银行分行对应表 as c
6  on b.所属分行 = c.分行号
7 where a.交易时间 between "2016-03-01" and "2016-03-31"
8       and a.交易类型 = "消费";

每个分行(分组group by)总交易金额(汇总求和sum)和分行对应的上级分行

代码语言:javascript
复制
1 select b.所属分行,
2        sum(a.交易金额) as 消费总金额,
3        c.上级分行
4 from交易表 as a
5 inner join 客户表 as b
6  on a.交易客户 = b.客户号
7 inner join 银行分行对应表 as c
8  on b.所属分行 = c.分行号
9 where a.交易时间 between "2016-03-01" and "2016-03-31"
10      and a.交易类型 = "消费"
11 group by b.所属分行;

查询结果如下

2)得出每个省行的消费总金额

将上面查询结果记为表d,通过观察可知

分行号为"4","2","3"属于江苏省分行

分行号"5","6","7"属于广东省分行

利用case when 对分行号做判断,符合条件的消费金额相加,得出各省分行的总消费金额。

代码语言:javascript
复制
1 select
2       sum(case when 上级分行 in ("4","2","3")
3                then 消费总金额 else null end )as "江苏省分行",
4       sum(case when 上级分行 in ("5","6","7")  
5                then 消费总金额 else null end ) as "广东省分行"
5 from d;

将上面的步骤1和步骤2和在一起就得到了最终的sql。

代码语言:javascript
复制
1 select
2        sum(case when 所属分行 in ("4","2","3")
3                 then 消费总金额 else null end )as "江苏省分行",
4        sum(case when 所属分行 in ("5","6","7") 
5                then 消费总金额 else null end ) as "广东省分行"
6   from
7    (select b.所属分行, 
8        sum(a.交易金额) as 消费总金额,
9            c.上级分行
10        from 交易表 a 
11          inner join 客户表 b on a.交易客户 = b.客户号
12           inner join 银行分行对应表 c on b.所属分行 = c.分行号
13         where 
14         a.交易时间 between "2016-03-01" and "2016-03-31"
15       and a.交易类型 = "消费" 
16      group by b.所属分行) as d;

查询结果如下

【本题考点】

本面试题通过与业务需求结合,考核SQL的综合能力,实际业务场景比较强,通过观察表之间的关系拆分问题写出业务需求。

1.如何将复杂的业务问题,使用多维度拆解分析方法去解决

2.遇到多条件判断的问题,要想到用case语句来实现

3.窗口函数的应用场景,①遇到排名问题,要想到使用窗口函数来实现。②对于“累计”问题,要想到用聚合函数作为窗口函数。比如累计求和,用sum。

4.通过观察数据表的关系,通过多表联结得出想要的字段

推荐:如何从零学会sql?

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
大数据
全栈大数据产品,面向海量数据场景,帮助您 “智理无数,心中有数”!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档