前言
最近写代码的时候遇到了个需求,刚开始想的时候,感觉不难,挺简单的,结果写的时候,各种思考、各种费脑,耗费了点时间,终于实现了。
需求:因为一些原因,数据库中有两个表,结构一样且数据不一样,现在需要对这两个表进行按照小时分组统计数据,然后展示在前台。
效果如下:
需要将两个表中各个时间段的数据相加,然后重新封装返回到前台做展示。
思路分析
- 分别按照小时分组查询两个表中的数据,查询出来的结构是一个
List<Map>
集合 - 先将第一个表的结果放在一个
map
集合中。 - 然后去遍历第二个结果的map集合,拿到
key
,去和第一个map
集合的key
比较,如果时间正好相等,则将两个结果的value
相加,最后得到一个总的map
集合 - 将总的
map
集合的键和值分别取出来放在VO
类中,最后在前台遍历展示。
下面贴一下实现代码。
代码实现
分别查询两个表中的数据,封装成List<Map>
的形式传出去。
public List<Map<String, Object>> getFlowsHoursDiSanFangByProvince(Integer proId){ Map<String,Object> map = new HashMap<String,Object>(); List<Map> mapList = new ArrayList<>(); List<Map<String, Object>> nameList = new ArrayList<>(); String sql=" SELECT SUM(acq_num_of_people) flows,DATE_FORMAT(acq_time,'%H') AS hours FROM base_disanfang \n" + " WHERE DATE(acq_time) = CURDATE()\n" + " AND province_id = ? \n" + " GROUP BY DATE_FORMAT(acq_time,'%H')"; Connection connection = null; PreparedStatement pStatement = null; connection = getConnection(); try { pStatement = connection.prepareStatement(sql); pStatement.setObject(1,proId); ResultSet rs=pStatement.executeQuery(); while(rs.next()){ map = new HashMap<String,Object>(); map.put("value",rs.getInt(1)); map.put("name",rs.getString(2)); nameList.add(map); } } catch (SQLException throwables) { throwables.printStackTrace(); } //return JSONArray.toJSONString(mapList); return nameList; }
public List<Map<String, Object>> getFlowsHoursThreeByProvince(Integer proId){ Map<String,Object> map = new HashMap<String,Object>(); List<Map<String, Object>> mapList = new ArrayList<>(); List<Map<String, Object>> nameList = new ArrayList<>(); String sql=" SELECT SUM(acq_num_of_people) flows,DATE_FORMAT(acq_time,'%H') AS hours FROM base_three " + " WHERE DATE(acq_time) = CURDATE() " + " AND province_id = ? " + " GROUP BY DATE_FORMAT(acq_time,'%H')"; Connection connection = null; PreparedStatement pStatement = null; connection = getConnection(); try { pStatement = connection.prepareStatement(sql); pStatement.setObject(1,proId); ResultSet rs=pStatement.executeQuery(); while(rs.next()){ map = new HashMap<String,Object>(); map.put("value",rs.getInt(1)); map.put("name",rs.getString(2)); nameList.add(map); } } catch (SQLException throwables) { throwables.printStackTrace(); } //return JSONArray.toJSONString(mapList); return nameList; }
开始处理List<Map>
结果集:
//根据省份编码获取小时段的客流信息(日客流趋势) basedisanfang的 List<Map<String, Object>> disanfangLists = zhiXingMysql.getFlowsHoursDiSanFangByProvince(proId); //根据省份编码获取小时段的客流信息(日客流趋势) basethree的 List<Map<String, Object>> threeLists = zhiXingMysql.getFlowsHoursThreeByProvince(proId); Map<Integer, Long> mapTotal = new HashMap<>(); //将数据放在map集合中 for (Map<String, Object> map : disanfangLists) { mapTotal.put(Integer.parseInt(map.get("name").toString()), Long.parseLong(map.get("value").toString())); } for (Map<String, Object> map : threeLists) { //获取basethree集合中的键 int threekey = Integer.parseInt(map.get("name").toString()); //获取mapTotal集合中的键,如果有,则相加,如果没有,则直接用 Set set = mapTotal.keySet(); for (Object hours : set) { //判断三方的里面有没有这个键 if (Integer.parseInt(hours.toString()) == threekey) { //有的话,加起来 Long flows = Long.parseLong(map.get("value").toString()) + mapTotal.get(threekey); //重新添加到map集合中,替换到原来的 mapTotal.put(threekey, flows); } } //获取basethree的所有键 Set basethreeSet = map.keySet(); Set mapTotalSet = mapTotal.keySet(); //遍历一下看看mapTotal里面有没有都加进去 Iterator ite1 = mapTotalSet.iterator(); Iterator ite2 = basethreeSet.iterator(); while (ite2.hasNext()) { if (mapTotalSet.contains(ite2.next())) { mapTotal.put(Integer.parseInt(map.get("name").toString()), Long.parseLong(map.get("value").toString())); } } } Set mapTotalSet = mapTotal.keySet(); List<Integer> hourList = new ArrayList<>();; List<Long> flowsList = new ArrayList<>(); //将键和值都放在VO中 for (Object hours : mapTotalSet) { hourList.add(Integer.parseInt(hours.toString())); flowsList.add(mapTotal.get(hours)); }
HomeVO
类的字段如下:
/** * @author: muxiongxiong * @date: 2021年11月27日 下午 1:31 * 公众号:雄雄的小课堂 * 博客:https://blog.csdn.net/qq_34137397 * 个人站:http://www.穆雄雄.com * 个人站:http://www.muxiongxiong.cn * @Description: 首页大屏的封装类 */ public class HomeVO { //客流排行 private List<Map<String, Object>> flowOrderByList = new ArrayList<>(); //场馆客流占比 private List<Object> flowZhanBiByDept = new ArrayList<>(); //月客流趋势 private List<BussFlowList> flowQuShiByMonth = new ArrayList<>(); //日客流趋势(暂时没有用) private Map<Integer, Long> flowQuShiByDays = new HashMap<>(); //客流前五的场馆信息 private List<Object> flowNameOrderFive = new ArrayList<>(); //小时客流趋势的小时 private List<Integer> hoursList = new ArrayList<>(); //小时客流趋势的客流 private List<Long> flowsList = new ArrayList<>(); public List<Map<String, Object>> getFlowOrderByList() { return flowOrderByList; } public void setFlowOrderByList(List<Map<String, Object>> flowOrderByList) { this.flowOrderByList = flowOrderByList; } public List<Object> getFlowZhanBiByDept() { return flowZhanBiByDept; } public void setFlowZhanBiByDept(List<Object> flowZhanBiByDept) { this.flowZhanBiByDept = flowZhanBiByDept; } public List<BussFlowList> getFlowQuShiByMonth() { return flowQuShiByMonth; } public void setFlowQuShiByMonth(List<BussFlowList> flowQuShiByMonth) { this.flowQuShiByMonth = flowQuShiByMonth; } public Map<Integer, Long> getFlowQuShiByDays() { return flowQuShiByDays; } public void setFlowQuShiByDays(Map<Integer, Long> flowQuShiByDays) { this.flowQuShiByDays = flowQuShiByDays; } public List<Object> getFlowNameOrderFive() { return flowNameOrderFive; } public void setFlowNameOrderFive(List<Object> flowNameOrderFive) { this.flowNameOrderFive = flowNameOrderFive; } public List<Integer> getHoursList() { return hoursList; } public void setHoursList(List<Integer> hoursList) { this.hoursList = hoursList; } public List<Long> getFlowsList() { return flowsList; } public void setFlowsList(List<Long> flowsList) { this.flowsList = flowsList; } }
最后是前端封装到echarts
中的代码,因为,如果现在是17点的话,则17点之后的数据应该为0才对,所以我这边的思路是先构建一个0-24小时的时间集合,直接扔到面积图的X轴,y轴则是从VO实体类中获取。
这边还会有个问题,就是查询的结果中可能有问题,比如7时没有数据,那么返回的结果就是5 6 8 9 时,没有7时,所以这个地方还需要进行一次与时间遍历判断一下,如果取的时间等于当前X轴的上的某时,才将数据放在Y轴的集合中,否则就填充0。
代码如下:
//根据省份获取每日客流趋势 //this.hoursList = null; if (this.hoursList.length === 0) { //构造小时 for (let i = 0; i < 24; i++) { this.hoursList.push(i + "时"); } } this.hoursFlowList = new Array(24).fill(0); for (var j = 0; j < this.homeVo.hoursList.length; j++) { //获取时间,且格式化一下 var shijian = this.homeVo.hoursList[j]; for (let i = 0; i < this.hoursFlowList.length; i++) { if (shijian == i) { this.hoursFlowList.splice(shijian, 1, this.homeVo.flowsList[j]); } } } /*这个不能放在括号外面,放外面执行的顺序不一样*/ this.drawLines("lines", this.hoursList, this.hoursFlowList); }) },
data
中声明的变量如下:
hoursList:[], //小时的集合 hoursFlowList:[], //小时段的客流集合 homeVo:[], //返回的数据结果
好了,到现在为止,已经都实现了,这种方法可能不是最好的方法,大家也可以说出你们的思路~