• SQL金融行业项目:你每月消费多少?(累计额,链表,case when)


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

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

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

     

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

     

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

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

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

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

    【解题步骤】

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

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

    1. select *
    2. from 交易表
    3. where 交易类型 = "消费" and year(交易时间) = 2016;

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

    1. select
    2. (case when year(交易时间) = 2016 and month(交易时间) = 1
    3. then 交易金额 else null end) as 20161月,
    4. (case when year(交易时间) = 2016 and month(交易时间) = 2
    5. then 交易金额 else null end) as 20162月,
    6. (case when year(交易时间) = 2016 and month(交易时间) = 3
    7. then 交易金额 else null end) as 20163
    8. from 交易表;

     

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

    1. select
    2. sum(case when year(交易时间) = 2016 and month(交易时间) = 1
    3. then 交易金额 else null end) as 20161月,
    4. sum(case when year(交易时间) = 2016 and month(交易时间) = 2
    5. then 交易金额 else null end) as 20162月,
    6. sum(case when year(交易时间) = 2016 and month(交易时间) = 3
    7. then 交易金额 else null end) as 20163
    8. from 交易表
    9. where 交易类型 = "消费" and year(交易时间) = 2016;

     

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

    1)2016年3月总消费金额

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

    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 *),同时交易类似是消费。

    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)。

    1. select a.客户名称,
    2. sum(b.交易金额) as 20163月总消费金额
    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》里讲过的窗口函数,语法如下。

    1. <窗口函数> over (partition by <用于分组的列名>
    2. order by <用于排序的列名>)

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

     

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

    1. select *
    2. from c
    3. where 累计消费金额>1288;

     

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

    1. select * ,
    2. row_number() over(partition by 交易客户
    3. order by 交易时间) as 排序
    4. from c
    5. where 累计消费金额>1288

     

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

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

    1. select *
    2. from d
    3. where 排序=1;

     

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

    1. select a.客户名称,e.交易时间 as 20163月首次达到1288的时间
    2. from 客户表 a inner join e
    3. on a.客户号 = e.交易客户;

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

    1. select a.客户名称,
    2. sum(b.交易金额) as 20163月总消费金额,
    3. e.交易时间 as 20163月首次达到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. from 交易表
    21. where 交易时间 between "2016-03-01" and "2016-03-31"
    22. and 交易类型 = "消费"
    23. ) as c where 累计消费金额>1288
    24. ) as d where 排序=1
    25. ) as e
    26. on a.客户号 = e.交易客户
    27. where b.交易时间
    28. between "2016-03-01" and "2016-03-31"
    29. and b.交易类型="消费"
    30. group by a.客户名称;

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

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

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

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

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

    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月份的消费数据

    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)和分行对应的上级分行 

    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 对分行号做判断,符合条件的消费金额相加,得出各省分行的总消费金额。

     

    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 d;

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

     

    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.通过观察数据表的关系,通过多表联结得出想要的字段

     

  • 相关阅读:
    Cadence Allegro如何添加/生成测试点?
    多条件变量应用--传送与搬运问题
    pthread_key_t和pthread_key_create()详解
    【2018年数据结构真题】
    C++保姆级入门教程(7)—— 循环结构
    Pulsar 各个Shedder分析及新的Shedder -- AvgShedder
    基于springboot+vue的公司员工工资资产管理系统 elementui
    ctfshow web入门 php特性 web126-web130
    机器学习中的特征选择:方法和 Python 示例
    Mysql时间范围查询不走索引问题
  • 原文地址:https://blog.csdn.net/qq_41404557/article/details/126155576