多个字段排序业务处理
2015-09-10 09:53
162 查看
写业务当中感觉最开始就是新建实体类和表,然后看需求,然后分析怎么去CUID操作,然后就开始去写SQL语句,使用Mybatis可以比较灵活的去解决ORM。这次挑战是对小时粒度的处理,解决方案是采用了部分的重构,提取方法和清晰的数据结构定义。
- 首先看一张表的结构:
describe [tableName];
已经存在表中的数据如下:
按照两个粒度,分别是日和小时。
日就是统计每天的人口数,返回1-24小时的人数,虽然大数据组可以提供24小时的数据,但是为了保证测试,我在业务里添加了该时间可能存在null的情况默认添0.因此返回给前端的总是24个横坐标。
order by 字段1,字段2.这样先按日排序在小时排序,这样方便处理。
首先获取参数startTime,endTime,areaId和粒度:
由于从timestamp时间戳的格式不便于处理,我需要去定义个我想要的格式,去转换,使用到了SimpleDateFormat类:
然后判断是否为精确到时:
这里dao层接口的方法定义了两个:
第一个会查询出所有的记录,第二个会采用聚合函数,合并同一天的人口数。
对应sqlmap分别为:
注意时间和小时的排序。
再回到action里:
我们获取所有记录并得到所有日期。
但是因为表里可能存在重复的日期数,因此有必要提取不重复的顺序排列的日期,我这里的getDateTimeList就是这个方法,如下定义:
图标是显示多天24时,key-value分别存储日期和对应的人数。
接下来去遍历所有日期,然后将对应日期所对应的24小时人数放到一个列表里,如果改小时没记录(测试可能用到,实际业务中会用记录为0),会用0去补齐:
然后还需要获取小时中的最大人数:
因为在日的粒度下也需要使用,因此方法采用了重构。
峰值的时间可能是多个,因此定义列表去保存:
后面的最小值,总人数,平均人口都采用了重构去解决,这样在日的粒度下去直接调用方法,简化了代码。在求平均的时候注意类型转换。
最后测试用例:
返回:
最开始tomcat一直报错无法注入,后来发现是服务层的注解没写。填上注解问题解决。
- 首先看一张表的结构:
describe [tableName];
已经存在表中的数据如下:
按照两个粒度,分别是日和小时。
日就是统计每天的人口数,返回1-24小时的人数,虽然大数据组可以提供24小时的数据,但是为了保证测试,我在业务里添加了该时间可能存在null的情况默认添0.因此返回给前端的总是24个横坐标。
order by 字段1,字段2.这样先按日排序在小时排序,这样方便处理。
select * from t_mon_data_pass_person_hour WHERE area_id = 7000 and date_time >= '2014-01-01' and date_time <= '2015-09-01' order by date_time,hour_time;
首先获取参数startTime,endTime,areaId和粒度:
//获取参数 String areaId = ParamUtil.getFilteredParameter(request, "areaId", 0, "7000"); String startTime = ParamUtil.getFilteredParameter(request, "startDate", 0, "2013-01-01"); String endTime = ParamUtil.getFilteredParameter(request, "endDate", 0, "2016-01-01"); Integer kpiCycle = Integer.valueOf(ParamUtil.getFilteredParameter(request, "kpiCycle", 0, "3"));
由于从timestamp时间戳的格式不便于处理,我需要去定义个我想要的格式,去转换,使用到了SimpleDateFormat类:
//定义查询map HashMap<String,String> queryMap = new HashMap<String,String>(); queryMap.put("areaId", areaId); queryMap.put("startTime", startTime); queryMap.put("endTime", endTime); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//定义格式
然后判断是否为精确到时:
if(kpiCycle == Constants.VISITOR_COUNT_UNIT_HOUR)
这里dao层接口的方法定义了两个:
getHourPassPersonList(queryMap) getDayPassPersonList(queryMap)
第一个会查询出所有的记录,第二个会采用聚合函数,合并同一天的人口数。
对应sqlmap分别为:
<select id="getHourPassPersonList" parameterType="java.util.Map" resultMap="BaseResultMap"> select * from t_mon_data_pass_person_hour <where> <if test="areaId != null"> area_id = #{areaId} </if> <if test="startTime != null"> <![CDATA[and date_time >= #{startTime}]]> </if> <if test="endTime != null"> <![CDATA[and date_time <= #{endTime}]]> </if> </where> order by date_time,hour_time </select>
注意时间和小时的排序。
<select id="getDayPassPersonList" parameterType="java.util.Map" resultMap="BaseResultMap"> select date_time,sum(population) as population from t_mon_data_pass_person_hour <where> <if test="areaId != null"> area_id = #{areaId} </if> <if test="startTime != null"> <![CDATA[and date_time >= #{startTime}]]> </if> <if test="endTime != null"> <![CDATA[and date_time <= #{endTime}]]> </if> group by date_time order by date_time </where> </select>
再回到action里:
我们获取所有记录并得到所有日期。
List<PassPerson> passPersonList = passPersonManager.getHourPassPersonList(queryMap); List<Date> daysList = getDateTimeList(passPersonList);
但是因为表里可能存在重复的日期数,因此有必要提取不重复的顺序排列的日期,我这里的getDateTimeList就是这个方法,如下定义:
//取出所有日期 private List<Date> getDateTimeList(List<PassPerson> list) { List<Date> dateList = new ArrayList<Date>(); for(PassPerson p : list) { if(!dateList.contains(p.getDateTime())) { dateList.add(p.getDateTime()); } } return dateList; }
图标是显示多天24时,key-value分别存储日期和对应的人数。
//定义结果 Map<String,List<Integer>> hourGraphMap = new TreeMap<String,List<Integer>>();
接下来去遍历所有日期,然后将对应日期所对应的24小时人数放到一个列表里,如果改小时没记录(测试可能用到,实际业务中会用记录为0),会用0去补齐:
for(Date date : daysList) { List<Integer> hoursList = new ArrayList<Integer>(); int time = 1;//初始化时间 for(PassPerson p : passPersonList) { if(sdf.format(p.getDateTime()).equals(sdf.format(date))) { //如果该小时存在记录 if(time == p.getHourTime()) { hoursList.add(p.getPopulation()); } //如果没时间记录,填0 else { for(int i = time;i < p.getHourTime();i ++) { hoursList.add(0); } hoursList.add(p.getPopulation()); time = p.getHourTime() + 1; } } } //0补齐 while(time < 24) { hoursList.add(0); time ++; } //格式转换 String datetime = sdf.format(date); hourGraphMap.put(datetime, hoursList); }
然后还需要获取小时中的最大人数:
//小时最大人数峰值 Integer hourMaxPopulation = getMaxPopulation(passPersonList);
因为在日的粒度下也需要使用,因此方法采用了重构。
//获得查出列表峰值 private Integer getMaxPopulation(List<PassPerson> list) { int max = 0; for(PassPerson p : list) { max = p.getPopulation() > max ? p.getPopulation() : max; } return max; }
峰值的时间可能是多个,因此定义列表去保存:
//获得最大峰值时的格式:yyyy-MM-dd H时 List<String> maxPopulationTimeList = new ArrayList<String>(); for(PassPerson p : passPersonList) { if(p.getPopulation().equals(hourMaxPopulation)) { Date date = p.getDateTime(); //格式转换 String dateOfString = sdf.format(date); maxPopulationTimeList.add(dateOfString + " " + p.getHourTime().toString()+"时"); } }
后面的最小值,总人数,平均人口都采用了重构去解决,这样在日的粒度下去直接调用方法,简化了代码。在求平均的时候注意类型转换。
//平均每小时的人口 Integer avgPopulationOfHour = 0; if(sumPopulation != 0) { Float f = (float)sumPopulation; Float f2 = (float)getDaysNumber(passPersonList) * 24; avgPopulationOfHour = (int) (f / f2); }
最后测试用例:
pass-person!display.action?areaId=7000&startDate=2014-01-01&endDate=2015-10-01&kpiCycle=0
返回:
{"hourMaxPopulation":400,"minPopulationTime":["2015-08-01 3时"],"maxPopulationTime":["2015-09-02 4时"],"avgPopulationOfHour":8,"hourMinPopulation":22,"topPopulation":400,"hourGraphMap":{"2015-08-01":[0,200,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"2015-08-02":[0,0,0,0,0,44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"2015-09-01":[200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"2015-09-02":[0,0,0,400,33,0,0,0,0,0,0,44,0,0,0,0,0,0,0,0,0,0,0,0],"2015-09-10":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,123]}}
最开始tomcat一直报错无法注入,后来发现是服务层的注解没写。填上注解问题解决。
相关文章推荐
- 黑马程序员—–常用工具类
- poi-单元格是公式
- jQuery中ajax - post() 方法实例详解
- Liferay 开发(三)
- 轻松搞定面试中的二叉树题目
- 利用 Google Translate 访问被禁网页
- 兔子--Service的生命周期
- Xcode 升级后,常常遇到的遇到的警告、错误,解决方法
- C++成员函数存储方式
- jQuery AJAX
- 来讲讲Git这个玩意到底该怎么用?
- Android开发文档之四种点击事件
- Leetcode #142 Linked List Cycle II
- cocos2d-js中监听帧事件时不要忘了this
- javaMail接收邮件
- 解决Eclipse发布webproject, jar无法发布到tomcat lib目录下的问题
- -fobjc-arc,使ARC与非ARC一块工作
- java logger
- mysql ftp或者镜像站点,提供各个版本资源
- 利用 Tinyproxy 搭建 HTTP(S) 代理