环比计算,算法是:先按照要求计算出一个时间段数据的分组统计作为A表(作为当前数据,假设今天为10.15日),然后将其时间+1个单位再次计算作为b表(实质是计算出前一天的数量放在当前天去对比,如下14日数据变为15日同一天的一个虚拟数据,主要是将前一天数据均向后一天移动一下),然后用a表对b表进行左联接查询,就有如下对应关系(通过时间将前一天数据和当天数据关联在一张表上),然后方便操作,sql语句如下:
a表时间 | 数据 | b表时间 | 数据 |
10.16 | 5 | ||
10.15 | 5 | 10.15 | 4 |
10.14 | 4 | 10.14 | 2 |
10.13 | 2 | 10.13 | |
作为当前数据 | 前一天数据 |
<select id="accountGrouwthRate" parameterType="map" resultType="map"> SELECT tt.currentTotal currentTotal,tt.time `time`, CASE WHEN tt.beforeTotal IS NULL OR tt.beforeTotal=0 THEN 0.00 ELSE FORMAT(((tt.currentTotal-tt.beforeTotal)/tt.beforeTotal)*100,2) END ratio FROM (SELECT m.current_total currentTotal,n.before_total beforeTotal,m.time FROM (SELECT COUNT(t.`id`) current_total , DATE_FORMAT(t.create_time,#{format}) `time` FROM u_account t WHERE t.`del_flag`=0 AND t.company_id=#{companyId} AND t.`create_time` BETWEEN DATE_FORMAT(#{time},#{outFormat}) AND DATE_FORMAT(DATE_ADD(#{time},INTERVAL #{num} ${outUnit}),#{outFormat}) GROUP BY DATE_FORMAT(t.create_time,#{format}) ) m LEFT JOIN (SELECT COUNT(t.`id`) before_total ,DATE_FORMAT(DATE_ADD(t.`create_time`,INTERVAL 1 ${unit}),#{format}) `time` FROM u_account t WHERE t.`del_flag`=0 AND t.company_id=#{companyId} AND t.`create_time` BETWEEN DATE_FORMAT(#{time},#{outFormat}) AND DATE_FORMAT(DATE_ADD(#{time},INTERVAL #{num} ${outUnit}),#{outFormat}) GROUP BY DATE_FORMAT(DATE_ADD(t.`create_time`,INTERVAL 1 ${unit}),#{format}) ) n ON m.time=n.time) tt </select>
在如上sql中,如果传入时间为”2018-10“想要查询2018-10~2018-11之间的数据,实际返回往往为空,那么我们需要将其变为2018-10-01~2018-11-01查询这个时间段的数据才可以,如上,我们为了兼容年月日的查询,我们将sql中的变化的部分采用占位符来标识,然后在代码里面组织我们的参数即可,组织参数代码如下:
private Map<String, Object> create_parameter(Map<String, Object> param,Integer num){ String time = (String) param.get("time"); int length = time.length(); String outFormat = null; String outUnit = null; String format = null; String unit = null; if(length==4){ time = time+"-01-01"; outFormat = "%Y-%m-%d"; outUnit = "YEAR"; format = "%Y-%m"; unit = "MONTH"; } if(length==7){ time = time+"-01"; outFormat = "%Y-%m-%d"; outUnit = "MONTH"; format = "%Y-%m-%d"; unit = "DAY"; } if(length==10){ outFormat = "%Y-%m-%d"; outUnit = "DAY"; format = "%Y-%m-%d %h"; unit = "HOUR"; } if(null!=outFormat && outUnit!=null && null!=format && unit!=null){ param.put("outFormat", outFormat); param.put("outUnit", outUnit); param.put("format", format); param.put("unit", unit); } param.put("time", time); param.put("num", num); return param; }
即可实现环比计算,同比计算的算法大同小异。