• sql同比环比计算


    题目:有两个表
    表一:销售明细

     表二:产品明细

    需求:查询2020年,每月的销售额,以及同比环比,并按照年月进行升序排序

    思路:分步操作

    1. 获得每月的数据
      首先的抽取时间,以及获得每个月的销售额,要有 销售额,两个表肯定是要连接起来的
      ------- 获取时间
      YEAR(字段名)—获取年份
      MONTH(字段名)----获取时间
    SELECT YEAR(s.sail_time) 年, MONTH(s.sail_time) 月 , SUM(s.number*p.pro_price) 销售额  
     FROM  sail_info s 
     LEFT JOIN produce_detail p
    ON s.produce_id=p.produce_id
    GROUP BY YEAR(s.sail_time) , MONTH(s.sail_time)  

    此处使用左连接的原因:是要补充销售表里单品的价格,要以左表为基准,要用了左连接
    结果:

    1. 单步操作获得同比数据
      同比:一般情况下是今年第n月与去年第n月比
      计算方式:同比增长率=(本期数-同期数)÷同期数×100%
      所以要有个本期数据与同期数据一一对应的表,那就要本期数据与同期数据分离
      有了第一步之后很容易获得数据
      本期数据:
    SELECT YEAR(s.sail_time) 年, MONTH(s.sail_time) 月 , SUM(s.number*p.pro_price) 销售额  
     FROM  sail_info s 
     LEFT JOIN produce_detail p
    ON s.produce_id=p.produce_id
    where YEAR(s.sail_time)=2020 
    GROUP BY YEAR(s.sail_time) , MONTH(s.sail_time)  

     同期数据:

    SELECT YEAR(s.sail_time) 年, MONTH(s.sail_time) 月 , SUM(s.number*p.pro_price) 销售额  
     FROM  sail_info s 
     LEFT JOIN produce_detail p
    ON s.produce_id=p.produce_id
    where YEAR(s.sail_time)=2019
    GROUP BY YEAR(s.sail_time) , MONTH(s.sail_time)  

    下面就要进行表的关联了
    本期、同期的区别就是年份不一样,月份一样呗,那就用月份作为连接点进行连接,代码和结果截图如下,同比就完成了~
    计算的是本期,本期数据是关键所以这边进行的是右连接—因为本期数据放在右边,放左边用左连接就好了
    ps:如果觉得这边跳了步骤的话可以将查询结果改成 * 先去查看关联之后的表

    SELECT  CONCAT(e,'-',a) 年月, b 月销售额, 
    CASE WHEN d>0 THEN CONCAT((b-d)/d*100,'') -- 转化为百分比,此处考虑到销售额为0的情况,分母不能为0,用case进行了条件判断
         ELSE "同期没有数据" END 同比  
         -- 这边的文字可以 换掉
     FROM 
    (SELECT YEAR(s.sail_time) f , MONTH(s.sail_time) c , SUM(s.number*p.pro_price) d FROM  sail_info s LEFT JOIN produce_detail p
    ON s.produce_id=p.produce_id  WHERE YEAR(s.sail_time)=2019 GROUP BY MONTH(s.sail_time)) s2 
    RIGHT JOIN 
    (SELECT YEAR(s.sail_time) e,MONTH(s.sail_time) a , SUM(s.number*p.pro_price) b  FROM  sail_info s LEFT JOIN produce_detail p
    ON s.produce_id=p.produce_id  WHERE YEAR(s.sail_time)=2020 GROUP BY MONTH(s.sail_time)) s1 
    ON s1.a=s2.c 

     

    3.单步操作获得环比数据
    环比:一般是指报告期水平与前一时期水平之比,此处指本月数据与上月数据
    计算方式:环比增长速度=(本期数-上期数)÷上期数×100%
    肯定也是要有表的关联了呗,怎么连呢???
    既然是计算2020年的环比,那就以要计算的为基础数据,进行表的关联
    上面已经有全部的年份、月份对应的数据,这一步主要是进行表的关联
    两个表进行关联:
    -1 2020年数据的表,即判断条件设置年份为2020的查询结果表
    -2 考虑到2020年一月份对应的是2019年的12月份,所以这个张表是不加判断条件的表,包含了2019年和2020年数据的表

    SELECT  *  FROM 
    (SELECT YEAR(s.sail_time) e,MONTH(s.sail_time) a , SUM(s.number*p.pro_price) 本期销售额  FROM  sail_info s LEFT JOIN produce_detail p
    ON s.produce_id=p.produce_id  WHERE YEAR(s.sail_time)=2020 GROUP BY MONTH(s.sail_time)) s1 
    LEFT JOIN 
    (SELECT YEAR(s.sail_time) f, MONTH(s.sail_time) g, SUM(s.number*p.pro_price) 上期销售额 FROM  sail_info s LEFT JOIN produce_detail p
    ON s.produce_id=p.produce_id GROUP BY MONTH(s.sail_time),YEAR(s.sail_time)) s3 
    ON ((s1.a-1)=s3.g AND s1.e=s3.f) OR (s1.a=1 AND s3.g=12 AND s3.f=2019)

     解析以下这个:

    (s1.a-1)=s3.g AND s1.e=s3.f  

    这个是针对2020年2月份的数据,2020 02-06 的数据与2020 01-05的数据一一对应
    按关联前的,a(月份)和g(月份)应该是相等的,因为对比的是上一期的,所以要错开,大的减掉等与小的
    那一月份怎么办呢??

    s1.a=1 AND s3.g=12 AND s3.f=2019

    这边就不能用上面的办法了,跨年了,所以需要用and连接的方式进行限制,而且需要限定为2019年的12月份,这边因为数据比较少,不限定年份也没问题

    两个部分用 or 并列存在,两个条件要分别用括号括起来,否则这个查询条件等于没有。。。。
    把* 换成

    CONCAT(e,'-',a) 年月,f 月销售额, 
     CASE WHEN h>0 THEN CONCAT((b-h)/h*100,'')
         ELSE "上期没有数据" END 环比

    执行查询:

    1. 最后一步,将数据放到一个表里~
      通过上述说明,可以发现都关联了2020年数据查询的表,所以可以将这个表放在中间 ,三个表进行关联(也是操作同比数据用右连接的原因)
    CASE WHEN d>0 THEN CONCAT((b-d)/d*100,'')
         ELSE "同期没有数据" END 同比 , 
     CASE WHEN h>0 THEN CONCAT((b-h)/h*100,'')
         ELSE "上期没有数据" END 环比
     FROM 
    (SELECT MONTH(s.sail_time) c , SUM(s.number*p.pro_price) d ,YEAR(s.sail_time) ye FROM  sail_info s LEFT JOIN produce_detail p
    ON s.produce_id=p.produce_id  WHERE YEAR(s.sail_time)=2019 GROUP BY MONTH(s.sail_time)) s2 
    RIGHT JOIN 
    (SELECT MONTH(s.sail_time) a , SUM(s.number*p.pro_price) b ,YEAR(s.sail_time) e FROM  sail_info s LEFT JOIN produce_detail p
    ON s.produce_id=p.produce_id  WHERE YEAR(s.sail_time)=2020 GROUP BY MONTH(s.sail_time)) s1 
    ON s1.a=s2.c 
    LEFT JOIN 
    (SELECT YEAR(s.sail_time) f, MONTH(s.sail_time) g, SUM(s.number*p.pro_price) h FROM  sail_info s LEFT JOIN produce_detail p
    ON s.produce_id=p.produce_id GROUP BY MONTH(s.sail_time),YEAR(s.sail_time)) s3 ON ((s1.a-1)=s3.g AND s1.e=s3.f) OR
    (s1.a=1 AND s3.g=12 AND s3.f=2019) ORDER BY CONCAT(e,'-',a) 

  • 相关阅读:
    [C/C++] 结构体内存对齐用法
    [其他] 关于C语言中使用未声明函数的问题
    [其他] 项目中的一个小问题
    【C++】DLL内共享数据区在进程间共享数据(重要)
    [MFC] CString小用例
    [C++] 频谱图中 FFT快速傅里叶变换C++实现
    [MFC] TabControl选项卡的使用
    [MFC] CFile读写文件实现(高效)
    [MFC] 编辑框 EditControl 输入数字范围限制
    [MFC] 对话框菜单项Menu选中打勾(单选,多选)
  • 原文地址:https://www.cnblogs.com/xiaohuhu/p/15638651.html
Copyright © 2020-2023  润新知