• SQL快出来,收快递啦(分区,case when 连表)


    【面试题】

    有一张“快递揽收表”,包含3列:运单号、客户id、创建日期。

    问题:查询运单创建日期在0501-0531期间不同单量区间的客户分布。最终得出的数据如下:

    【解题步骤】

    1. 汇总分析

    计算0501-0531期间每个客户的单量,涉及到“每个”,要想到《猴子 从零学会SQL》里讲过的用分组汇总来解决这类问题。按“客户id”分组,对“运单号”统计数目得到单量(count),注意要用distinct对运单号去重

    1. select 客户id,
    2. count(distinct 运单号) as 单量
    3. from 快递揽收表
    4. where 创建日期 >= ‘2020-05-01and 创建日期 <= ‘2020-05-31
    5. group by 客户id;

     

    2. 子查询

    在上一步的基础上,还无法得到要求的“最终结果”。因为,“最终结果”里面获取的是不同单量区间的客户数量分布。

    所以,还要在上一步的基础上(作为子查询)获取不同客户所处的单量区间。不同区间这种问题怎么办呢?

    要想到《猴子 从零学会SQL》里讲过的多条件判断,也就是用到case语句

    1. select 客户id,单量,
    2. (case when 单量 <= 5 then0-5
    3. when 单量 >= 6 and 单量 <= 10 then6-10
    4. when 单量 >= 11 and 单量 <= 20 then11-20
    5. else20以上’
    6. end) as 单量区间
    7. from
    8. (
    9. select 客户id,
    10. count(distinct 运单号) as 单量
    11. from 快递揽收表
    12. where 创建日期 >= ‘2020-05-01and 创建日期 <= ‘2020-05-31
    13. group by 客户id
    14. ) as t1;

     

    但是和最终结果对比发现,还需要得到客户数,怎么办?

    在上一步查询结果的基础上(作为子查询),再使用一次汇总分析,按“单量区间”分组(group by),对客户id汇总得到客户数(count)。

    1. select 单量区间 as 单量,
    2. count(distinct 客户id) as 客户数
    3. from
    4. (
    5. select 客户id
    6. ,单量
    7. ,case when 单量 <= 5 then0-5
    8. when 单量 >= 6 and 单量 <= 10 then6-10
    9. when 单量 >= 11 and 单量 <= 20 then11-20
    10. else20以上’ end as 单量区间
    11. from
    12. (
    13. select 客户id
    14. ,count(distinct 运单号) as 单量
    15. from 快递揽收表
    16. where 创建日期 >= ‘2020-05-01and 创建日期 <= ‘2020-05-31
    17. group by 客户id
    18. ) as t1
    19. ) as t2
    20. group by 单量区间;

     

    【本题考点】

    1.当遇到“每个”这类问题,要想到用分组汇总或者窗口函数 

    2.考查对子查询的灵活使用,嵌套了两次子查询,也就是把上一步查询结果作为子查询

    3.考查对常见函数的了解:count()、group by()、distinct、case when,以及它们的组合使用

    4.当遇到“区间”问题的时候,要想到用多条件判断(case语句)解决

    5.考察遇到业务问题,如何用逻辑树分析方法把复杂问题变成矿业解决的子问题

    【举一反三】

    查询运单创建日期在0501-0531期间不同单量区间的客户占比。

    与原答案的区别是:最终查询的结果是客户占比。

     

    所以,需要查询客户总数;然后使用多表查询来计算客户占比。

    1. select count(distinct 客户id) as 客户总数
    2. from 快递揽收表
    3. where 创建日期 >= ‘2020-05-01and 创建日期 <= ‘2020-05-31’;

     

    将原答案与“客户总数”联结,同时使用concat()函数将小数转化成百分数。

     

    1. select a.单量,
    2. concat(round(a.客户数/b.客户总数,4)*100,’%’) as 客户占比
    3. from
    4. (
    5. select 单量区间 as 单量
    6. ,count(distinct 客户id) as 客户数
    7. from
    8. (
    9. select 客户id
    10. ,单量
    11. ,case when 单量 <= 5 then0-5
    12. when 单量 >= 6 and 单量 <= 10 then6-10
    13. when 单量 >= 11 and 单量 <= 20 then11-20
    14. else20以上’ end as 单量区间
    15. from
    16. (
    17. select 客户id
    18. ,count(distinct 运单号) as 单量
    19. from 快递揽收表
    20. where 创建日期 >= ‘2020-05-01and 创建日期 <= ‘2020-05-31
    21. group by 客户id
    22. ) as t1
    23. ) as t2
    24. group by 单量区间
    25. ) as a
    26. left join
    27. (
    28. select count(distinct 客户id) as 客户总数
    29. from 快递揽收表
    30. where 创建日期 >= ‘2020-05-01and 创建日期 <= ‘2020-05-31
    31. ) as b
    32. on 1 = 1;

    转载于公众号:猴子数据分析 

  • 相关阅读:
    Docker基础入门详解
    vmware虚拟机中的archlinux无法播放声间的解决办法
    vue-grid-layout移动卡片到页面底部时页面滚动条跟随滚动
    第三章-Mybatis源码解析-以xml方式走流程-mapper解析(一)
    安卓定时任务单例
    flutter使用getx实现路由跳转,页面没有执行dispose
    场景应用:id全局唯一且自增,如何实现?
    【R】数据相关性的可视化
    怎么高效学习Java进阶技能 需要掌握哪些知识
    软件定制vs现成,定制软件开发的优势
  • 原文地址:https://blog.csdn.net/qq_41404557/article/details/126159625