Java 同环比计算相关逻辑

  • 相关概念
  • 背景
  • 实现思路
  • 具体代码
  • SQL实现方式[Mysql]
    • 按月进行分组同比 2022年/2020年各月数据同比
    • 按月进行分组同比 各月数据环比

相关概念

「同比」
与历史「同时期]比较,例如2011年3月份与2010年3月份相比,叫「同比」。
同比是“同期”的比较,中间有可能跨了若干个统计周期,或者没有跨越一个统计周期。跨越了若干个统计周期的同比与环比不一样,而一个统计周期也没有跨越的同比实际上与环比是一样的
同比是“同期”的比较,中间有可能跨了若干个统计周期,或者没有跨越一个统计周期。跨越了若干个统计周期的同比与环比不一样,而一个统计周期也没有跨越的同比实际上与环比是一样的
「环比」
与「上一个」统计周期比较,例如2011年4月份与2011年3月份相比较,称为「环比」。
本期环比增长(下降)率(%) = (本期价格/上期价格 — 1 )× 100%
本期同比增长(下降)率(%) = (本期价格/上年同期价格 —1) × 100%

背景

项目中使用了不同种数据库,为了减少工作量,不在数据库层进行同环比计算(需要查看不同数据库函数语法).所以决定在代码层面实现

实现思路

使用标记,或者缓冲避免多次循环数据
环比
1.降序排序
2.环比计算
循环结果集(不连续时间区间)
取标记位数据(标记位默认为1)使用下标
根据日期判断是不是相邻区间
如果是->直接计算,标志位➕1
如果不是->结果为0,标志位不变
时间复杂度O(n)

同比
1.升序排序
2.同比计算(不连续时间区间)
设置缓冲时间区间数据List<Map(以年,不同月为key)>
与缓冲区间判断年是否是相邻年(默认比较相邻年)
如果是->取对应的月数据
取到数据,计算
取不到,结果为0
如果不是->本年度所有月同比为0
时间复杂度为O(n)

具体代码

方法无法直接使用,需要结合自己逻辑改进


private List<Map<String, Object>> momYoyData(List<Map<String, Object>> obj,QueryDataSetBo bo){Map<String, Object> momCOUNTSet = bo.getMomCOUNTSet();//时间字段String fieldName = (String)momCOUNTSet.get("fieldName");String timeFieldKey=null;//时间字段类型【年,月,日,周,季,半年度】int type=(int)momCOUNTSet.get("type");switch (type){case 1:timeFieldKey="date_format(column, '%Y')".replace("column",fieldName);break;case 2:timeFieldKey="date_format(column, '%Y-%m')".replace("column",fieldName);break;case 3:timeFieldKey="date_format(column, '%Y-%m-%d')".replace("column",fieldName);break;case 4:timeFieldKey="date_format(column,'%Y-%u')".replace("column",fieldName);break;case 5:timeFieldKey="concat(date_format(column, '%Y'),'-',FLOOR((date_format(column, '%m')+2)/3))".replace("column",fieldName);break;case 6:timeFieldKey="concat(date_format(column, '%Y'),'-',CEIL((date_format(column, '%m'))/6))".replace("column",fieldName);break;default:break;}//数据字段List<Map<String, Object>> dataFieldName = (List<Map<String, Object>>)momCOUNTSet.get("dataFieldName");ArrayList<String> yoyfieldList = new ArrayList<>(); //同比字段listArrayList<String> momfieldList = new ArrayList<>(); //环比字段listfor (Map<String, Object> stringObjectMap : dataFieldName) {String value = String.valueOf(stringObjectMap.get("value"));String compute = String.valueOf(stringObjectMap.get("compute"));String dataFieldkey=value+"_"+compute;if ((int)stringObjectMap.get("momYoyType")==1){//同比yoyfieldList.add(dataFieldkey);}else if ((int)stringObjectMap.get("momYoyType")==2){//环比momfieldList.add(dataFieldkey);}}//同比//升序List<Map<String, Object>> yoyDataList =new ArrayList<>();List<Map<String, Object>> maps =new ArrayList<>(obj);String finalTimeFieldKey=timeFieldKey;Collections.sort(maps, new Comparator<Map<String, Object>>() {@Overridepublic int compare(Map<String, Object> o1, Map<String, Object> o2) {String o11 = (String)o1.get(finalTimeFieldKey);String o22 = (String)o2.get(finalTimeFieldKey);return o11.compareTo(o22);}});if (yoyfieldList!=null&&yoyfieldList.size()>0){Map<String, Object> bufferMap = new HashMap<>();for (int i = 0; i < maps.size(); i++) {Map<String, Object> newMap=new HashMap<>();Map<String, Object> map=maps.get(i);newMap.putAll(map);String time = (String) map.get(finalTimeFieldKey);String[] split = time.split("-");String year=split[0];String time2=split[1];String lastYear = getLastYear(year);if (bufferMap.containsKey(lastYear)&&bufferMap.get(lastYear)!=null){HashMap<String, Object > dataMap = (HashMap<String, Object>)bufferMap.get(lastYear);for (String yoyfield : yoyfieldList) {if (dataMap.containsKey(time2)||dataMap.get(time2)!=null){Map<String, Object> databufferMap = (Map<String, Object>)dataMap.get(time2);if (map.containsKey(yoyfield)&&map.get(yoyfield)!=null&&databufferMap.containsKey(yoyfield)&&databufferMap.get(yoyfield)!=null){BigDecimal p = new BigDecimal((Double) map.get(yoyfield));BigDecimal q = new BigDecimal((Double) databufferMap.get(yoyfield));BigDecimal rate = new BigDecimal(0.000000);rate=(p).divide(q,3, RoundingMode.HALF_UP);newMap.put(yoyfield+"_"+"yoy",Double.valueOf(rate.toString()));}else {newMap.put(yoyfield+"_"+"yoy",0);}}else {newMap.put(yoyfield+"_"+"yoy",0);}}}else {for (String yoyfield : yoyfieldList) {newMap.put(yoyfield+"_"+"yoy",0);}}yoyDataList.add(newMap);//操作缓冲MaPif (i==0){Map<String, Object> dataMap=new HashMap<>();dataMap.put(time2,map);bufferMap.put(year,dataMap);}else{if (bufferMap.containsKey(year)&&bufferMap.get(year)!=null){HashMap<String, Object > dataMap = (HashMap<String, Object>)bufferMap.get(year);dataMap.put(time2,map);bufferMap.put(year,dataMap);}else {Map<String, Object> dataMap=new HashMap<>();dataMap.put(time2,map);bufferMap.put(year,dataMap);}}}}//环比//升序List<Map<String, Object>> maps2 =new ArrayList<>(obj);Collections.sort(maps2, new Comparator<Map<String, Object>>() {@Overridepublic int compare(Map<String, Object> o1, Map<String, Object> o2) {String o11 = (String)o1.get(finalTimeFieldKey);String o22 = (String)o2.get(finalTimeFieldKey);return o22.compareTo(o11);}});List<Map<String, Object>> momDataList =new ArrayList<>();if (momfieldList!=null&&momfieldList.size()>0){for (int i = 0; i < maps2.size(); i++) {Map<String, Object> map=maps2.get(i);Map<String, Object> newMap=new HashMap<>();newMap.putAll(map);if (i==maps2.size()-1){for (String momfield : momfieldList) {newMap.put(momfield+"_"+"mom",0);}}else {Map<String, Object> nextMap=maps2.get(i+1);String time = (String) map.get(finalTimeFieldKey);String nextTime = (String) nextMap.get(finalTimeFieldKey);if (isContinuous(time,nextTime,type)) {for (String momfield : momfieldList) {if (map.containsKey(momfield)&&map.get(momfield)!=null&&nextMap.containsKey(momfield)&&nextMap.get(momfield)!=null){BigDecimal p = new BigDecimal((Double) map.get(momfield));BigDecimal q = new BigDecimal((Double) nextMap.get(momfield));BigDecimal rate = new BigDecimal(0.000000);rate=(p).divide(q,3, RoundingMode.HALF_UP);newMap.put(momfield+"_"+"mom",Double.valueOf(rate.toString()));}else {newMap.put(momfield+"_"+"mom",0);}}}else {for (String momfield : momfieldList) {newMap.put(momfield+"_"+"mom",0);}}}momDataList.add(newMap);}}obj.addAll(momDataList);obj.addAll(yoyDataList);List<Map<String, Object>> merge = merge(obj, timeFieldKey);Collections.sort(merge, new Comparator<Map<String, Object>>() {@Overridepublic int compare(Map<String, Object> o1, Map<String, Object> o2) {String o11 = (String)o1.get(finalTimeFieldKey);String o22 = (String)o2.get(finalTimeFieldKey);return o11.compareTo(o22);}});return merge;}private String getLastYear(String year){SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy");try {Date parse = simpleDateFormat.parse(year);Calendar cal=Calendar.getInstance();cal.setTime(parse);cal.add(Calendar.YEAR,-1);Date time = cal.getTime();return simpleDateFormat.format(time);} catch (ParseException e) {return null;}}private String getlastDay(String daystr){SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");try {Date parse = simpleDateFormat.parse(daystr);Calendar c = Calendar.getInstance();c.setTime(parse);int day=c.get(Calendar.DATE);c.set(Calendar.DATE,day-1);return new SimpleDateFormat("yyyy-MM-dd").format(c.getTime());} catch (Exception e) {return null;}}private boolean isContinuous(String time,String nextTime,Integer type){boolean isContinuous=false;String[] split = time.split("-");String yearTime=split[0];String timeTime=split[1];String[] split2 = nextTime.split("-");String yearNextTime=split2[0];String timeNextTime=split2[1];switch (type){case 1:if (yearNextTime.equals(getLastYear(yearTime))){isContinuous=true;}break;case 2:if (yearTime.equals(yearNextTime)){if (Integer.valueOf(timeTime)-Integer.valueOf(timeNextTime)==1){isContinuous=true;}}if (yearNextTime.equals(getLastYear(yearTime))){if (Integer.valueOf(timeTime)==1&&Integer.valueOf(timeNextTime)==12){isContinuous=true;}}break;case 3:if (getlastDay(time).equals(nextTime)){isContinuous=true;}break;case 4:if (yearTime.equals(yearNextTime)){if (Integer.valueOf(timeTime)-Integer.valueOf(timeNextTime)==1){isContinuous=true;}}if (yearNextTime.equals(getLastYear(yearTime))){if ((Integer.valueOf(timeTime)==1&&Integer.valueOf(timeNextTime)!=0&&(Integer.valueOf(timeNextTime)==52||Integer.valueOf(timeNextTime)==53))||(Integer.valueOf(timeTime)==0&&(Integer.valueOf(timeNextTime)==52||Integer.valueOf(timeNextTime)==53))){isContinuous=true;}}break;case 5:if (yearTime.equals(yearNextTime)){if (Integer.valueOf(timeTime)-Integer.valueOf(timeNextTime)==1){isContinuous=true;}}if (yearNextTime.equals(getLastYear(yearTime))){if (Integer.valueOf(timeTime)==1&&Integer.valueOf(timeNextTime)==4){isContinuous=true;}}break;case 6:if (yearTime.equals(yearNextTime)){if (Integer.valueOf(timeTime)-Integer.valueOf(timeNextTime)==1){isContinuous=true;}}if (yearNextTime.equals(getLastYear(yearTime))){if (Integer.valueOf(timeTime)==1&&Integer.valueOf(timeNextTime)==2){isContinuous=true;}}break;default:break;}return isContinuous;}public static List<Map<String, Object>> merge(List<Map<String, Object>> m1,String mergeKey){Set<String> set = new HashSet<>();System.out.println("m1的数据格式是:"+m1);return m1.stream().filter(map->map.get(mergeKey)!=null).collect(Collectors.groupingBy(o->{//暂存所有keyset.addAll(o.keySet());//按mergeKey分组return o.get(mergeKey).toString();})).entrySet().stream().map(o->{//合并Map<String, Object> map = o.getValue().stream().flatMap(m->{return m.entrySet().stream();}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a,b)->b));//为没有的key赋值0set.stream().forEach(k->{if(!map.containsKey(k)) map.put(k, 0);});return map;}).collect(Collectors.toList());}

SQL实现方式[Mysql]

-- 年【普通年】/【闰年】
SELECTdate_format(time1, '%Y'),round( sum( time1_data ) / 1, 1 )
FROMtime_test WHERE time1  is not null
GROUP BY
date_format(time1, '%Y')-- 月【普通年】/【闰年】
SELECTdate_format(time1, '%Y-%m'),round( sum( time1_data ) / 1, 1 )
FROMtime_test WHERE time1  is not null
GROUP BY
date_format(time1, '%Y-%m')-- 日【普通年】/【闰年】
SELECTdate_format(time1, '%Y-%m-%d'),round( sum( time1_data ) / 1, 1 )
FROMtime_test WHERE time1  is not null
GROUP BY
date_format(time1, '%Y-%m-%d')-- 季度 【普通年】/【闰年】
SELECTconcat(date_format(time1, '%Y'),'--',FLOOR((date_format(time1, '%m')+2)/3)),round( sum( time1_data ) / 1, 1 )
FROMtime_test
WHERE time1  is not null
GROUP BY
concat(date_format(time1, '%Y'),'--',FLOOR((date_format(time1, '%m')+2)/3))-- 半年度 【普通年】/【闰年】
SELECTconcat(date_format(time1, '%Y'),'--',CEIL((date_format(time1, '%m'))/6)),round( sum( time1_data ) / 1, 1 )
FROMtime_test
WHERE time1  is not null
GROUP BY
concat(date_format(time1, '%Y'),'--',CEIL((date_format(time1, '%m'))/6))-- 周 【普通年】/【闰年】SELECTDATE_FORMAT(time1,'%Y%u'),round( sum( time1_data ) / 1, 1 )
FROMtime_test
WHERE time1  is not null
GROUP BY
DATE_FORMAT(time1,'%Y%u')

按月进行分组同比 2022年/2020年各月数据同比

-- 按月进行分组同比 2022年/2020年各月数据同比
SELECT
a1.time,
a1.`month`,
ifnull(round(a1.`DATA`/b1.`DATA`,2),0) AS 同比
FROM
(
-- 2022年各月数据
SELECT
time,
`DATA`,
SUBSTRING_INDEX(time,"-",-1)  AS `month`
from (
SELECTdate_format(time1, '%Y-%m') AS time,round( sum( time1_data ) / 1, 1 )   AS `DATA`
FROMtime_test WHERE time1  is not null ANDdate_format(time1, '%Y')='2022'
GROUP BY
date_format(time1, '%Y-%m')
) a
) a1
LEFT JOIN
(
-- 2020年各月数据
SELECT
time,
`DATA`,
SUBSTRING_INDEX(time,"-",-1)  AS `month`
from (
SELECTdate_format(time1, '%Y-%m') AS time,round( sum( time1_data ) / 1, 1 )   AS `DATA`
FROMtime_test WHERE time1  is not null ANDdate_format(time1, '%Y')='2020'-- 非连续性数据AND date_format(time1, '%Y-%m') !='2020-05'
GROUP BY
date_format(time1, '%Y-%m')
) b
) b1
ON a1.`month`=b1.`month`

按月进行分组同比 各月数据环比

SELECT
a1.time,
b1.time,
ifnull(round(a1.`DATA`/b1.`DATA`,2),0) AS 环比,
a1.`DATA`,
b1.`DATA`
FROM
(
SELECT
time,
`DATA`,
SUBSTRING_INDEX(time,"-",1)   AS `year`,
SUBSTRING_INDEX(time,"-",-1)  AS `month`
from (
SELECTdate_format(time1, '%Y-%m') AS time,round( sum( time1_data ) / 1, 1 )   AS `DATA`
FROMtime_test WHERE time1  is not null
GROUP BY
date_format(time1, '%Y-%m')
) a
) a1
LEFT JOIN
(
SELECT
time,
`DATA`,
SUBSTRING_INDEX(time,"-",1)   AS `year`,
SUBSTRING_INDEX(time,"-",-1)  AS `month`
from (
SELECTdate_format(time1, '%Y-%m') AS time,round( sum( time1_data ) / 1, 1 )   AS `DATA`
FROMtime_test WHERE time1  is not null
GROUP BY
date_format(time1, '%Y-%m')
) b
) b1
ON a1.`year`=b1.`year` AND a1.`month`=b1.`month`+1
ORDER BY a1.time desc

Java 同环比计算相关逻辑相关推荐

  1. Java常用类(数学相关类 /字符串相关类/时间相关类/格式化类)

    Java类库概述 Java类库文档 https://docs.oracle.com/javase/8/docs/api/ 可以下载文档离线版本(chm格式) https://blog.csdn.net ...

  2. 分布式实时计算—实时计算相关问题及解决方案

    原文作者:孟知之 原文地址:实时计算相关问题及解决方案 目录 1. 怎么处理 Spark structured streaming 慢速变化数据 join 的问题? 2. Kafka不稳定导致Spar ...

  3. 当Java遇上机密计算,又一段奇幻之旅开始了!

    简介: 汪少军:如何为Java业务提供机密计算保护? 写在前面 在信息世界里,数据存在三种状态: 存储态.传输态和计算态.存储在数据库或磁盘中的数据属于存储状态,在网络中传输的数据属于传输状态,正在被 ...

  4. kotlin实现的简单个人账户管理APP(三) 自定义View仿支付宝的密码输入框/密码相关逻辑

    转载请注明出处:http://blog.csdn.net/a512337862/article/details/78874322 前言 1.本篇博客相关的项目介绍请参考基于kotlin实现的简单个人账 ...

  5. java中对象的清除 正确的说法是_下列关于Java中垃圾回收的相关说法,正确的是()...

    [简答题]审证中要审核的要点有哪些? [单选题]幼儿以积木.雪.沙土等材料为道具来模仿周围现实生活的游戏是( ) [简答题]What is the requirements & what ' ...

  6. 使用numpy计算相关系数矩阵:np.corrcoef()

    [小白从小学Python.C.Java] [Python-计算机等级考试二级] [Python-数据分析] 使用numpy计算相关系数矩阵 np.corrcoef() 选择题 关于以下代码说法错误的是 ...

  7. 【项目实战】——Java根据奖品权重计算中奖概率实现抽奖(适用于砸金蛋、大转盘等抽奖活动)...

    Java根据奖品权重计算中奖概率实现抽奖http://www.bieryun.com/1035.html 双蛋节(圣诞+元旦)刚刚过去,前几天项目上线的砸金蛋活动也圆满结束. 现在在许多网站上都会有抽 ...

  8. 用MDX进行同比及环比计算

    同比和环比计算是企业应用.电子商务应用中常用的计算方法,也是常用的数据分析手段.写这篇文章也是因为最近在学习MDX相关的一些计算方法的同时回想到原来我在项目中使用过的一些类似的,利用SQL来完成的统计 ...

  9. JAVA日期时间的计算

    最近,手头有不少项目,其中就有一个类似公文流转的项目,其中有一个模块是任务的制定,而在任务的类型中有一个循环任务,就是用户输入任务的开始日期.结束日期,还需要输入一个周期数,比如每周的星期几.每月的多 ...

  10. 利用JAVA中关于继承的相关知识求得圆柱体体积并输出

    利用JAVA中关于继承的相关知识求得圆柱体体积并输出 Write a program: 1)Define a Circle class and a Cylinder class, which is d ...

最新文章

  1. (数据库系统概论|王珊)第七章数据库设计-第二节:需求分析
  2. 电商首焦素材的万能构图模板
  3. C++static类静态成员函数及变量解析
  4. mysql8.0.17压缩包安装教程_mysql 8.0.17 解压版安装配置方法图文教程
  5. c++ 未定义标识符string_Redis之String的数据结构
  6. Python GUI 编程
  7. 堆和栈的概念和区别?
  8. 深入解读Linux进程调度Schedule
  9. Opencv中convertTo函数
  10. java cxf调用webservice_Java调用WebService方法总结(7)--CXF调用WebService
  11. 竞态条件的赋值_Go 译文之竞态检测器 race
  12. C语言函数定义和函数调用
  13. dvm 与jvm 区别
  14. 自己制作dns解析服务器,如何使用自己的DNS服务器解析域名,架设自己的DNS服务器...
  15. 【渝粤题库】陕西师范大学202021宏观经济学作业(高起本、专升本)
  16. android 音频播放时小喇叭动画
  17. APS计划排产软件助家纺企业进行成本控制
  18. VS2019 莫名其妙出现: C2059 语法错误:“}“,C2143 语法错误:缺少“;“(在“}“的前面),C2065 未定义标识符,C2039 不是““的成员等
  19. SQL Server 中的身份认证讲解
  20. java大小写敏感_Java是大小写敏感的语言。

热门文章

  1. sap销售发货的流程_现金及快速销售流程
  2. HTML生成Word文档,可自定义Word文档页眉、页脚、分页。
  3. 关于数据分析岗位的工作思考
  4. oracle rac查看节点及宕库
  5. 关键词文章生成器-智能关键词文章生成器
  6. 数据预处理(数据审核、缺失值处理、标准化正则化、降维等)
  7. python解二元一次方程组 迭代法_解二元一次方程组多种方法
  8. 现在学 Prolog 递归
  9. win7找不到服务器的dns错误怎么办,Win7系统DNS错误怎么办?
  10. 基于PID算法的房间温度控制及Python程序