为什么使用行转列
有些时候,因为业务问题,我们需要对附表数据进行行转列,比如:工厂中在对产品排生产计划时,会排每一天生产多少产品,而这个每天生产多少是滚动的,这个月有,下个月也有,下一年也有可能有,所以用主附表的方式表现就不是很直观,所以也就需要用到行转列表现到一个表里,再根据时间进行筛选,选择看那一段时间的。
表现形式:
后端实现行转列的方法
为了能重复使用,我写了一个实现行转列的方法:
上代码:
package org.jeecg.common.util;
import org.jeecg.common.exception.JeecgBootException;
import java.util.*;
/**
* @author dawei
*/
public class RowTransforColumn {
/**
* 进行行转列(主附表式)
* @param mainData 主表数据
* @param detailData 附表数据
* @param relationshipInMain 主表关系字段集合 (请按照对应顺序存放)
* @param relationshipInDetail 副表关系字段集合 (请按照对应顺序存放)
* @param transforColumn 要进行行转列的字段 (字段名)
* @param reansforDate 要进行行转列的字段数据 (字段名)
* @param detailColumns 附表列(可不传,如果需要让行转列后的数据 只要某些列 就要填)如果不填请传”null“
* @param defaultValue 行转列的列的默认值
* @return 合并后的数据放在主表中返回
*/
public static List<Map<String,Object>> rowTransforColumn(List<Map<String,Object>> mainData,List<Map<String,Object>> detailData,List<String> relationshipInMain,List<String> relationshipInDetail,String transforColumn,String reansforDate,List<String> detailColumns,Object defaultValue){
// //存放行转列后的结果
// List<Map> res = new LinkedList<>();
// Map<String,List<Map<String,Object>>> details = new HashMap<>();
Map<String,Object> detailMaps = new HashMap<>();
//记录准备指定列
if (detailColumns!=null){
for(String column:detailColumns){
detailMaps.put(column,defaultValue);
}
}else {
//指定列为空 自动定位 遍历附表数据
for (Map<String,Object> map:detailData){
Object object = map.get(transforColumn);
if (object == null){
throw new JeecgBootException("转置的列在附表中不存在");
}
//如果附表数据对应日期存在
if (!detailMaps.containsKey(object.toString())){
//放入列中
detailMaps.put(object.toString(),defaultValue);
}
}
}
//记录映射关系
Map<String,Map<String,Object>> mainDateMap = new HashMap<>();
for (Map<String,Object> mainMap : mainData){
//多个关系列组成的唯一标识
String key = "";
for (String relation:relationshipInMain){
Object object = mainMap.get(relation);
if (object==null){
throw new JeecgBootException("关系列:"+relation+",在主表中不存在");
}
key+=object.toString()+",";
}
mainMap.putAll(detailMaps);
mainDateMap.put(key,mainMap);
}
//遍历附表数据
for (Map<String,Object> map:detailData){
//多个关系列组成的唯一标识
String key = "";
for (String relation:relationshipInDetail){
Object object = map.get(relation);
if (object==null){
throw new JeecgBootException("关系列:"+relation+",在副表中不存在");
}
key+=object.toString()+",";
}
//找关联关系 主表数据
Map<String,Object> mainMap = mainDateMap.get(key);
if (mainMap!=null){
//添加到主表中
mainMap.replace(map.get(transforColumn).toString(),map.get(reansforDate));
}
}
return mainData;
}
}
注意事项
- 代码参数,主表数据和附表数据都是map类型;
- 主表数据和附表数据必须有关联关系。
- 他们的关系字段可以是多个。但是必须按顺序一一对应;
- 附表行转列后的数据是直接放进主表数据集合中的;
- 代码中使用的异常,需要自己进行定义。或者直接抛出Exception也可以。
使用例子:
测试方法
package rowToColumn;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
public class test {
public static void main(String[] args) {
//主表数据
List<Map<String,Object>> planMains = new LinkedList<>();
for (int i = 0;i<10;i++){
Map<String,Object> mainMap = new HashMap<>();
mainMap.put("plan_no",i);
mainMap.put("name","jihua"+i);
mainMap.put("erp_code","chanpin"+i);
planMains.add(mainMap);
}
//附表数据
List<Map<String,Object>> planDetails = new LinkedList<>();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Random random = new Random();
for (int i =0;i<10;i++){
for (int t = 0;t<5;t++){
Date date=new Date();
Calendar calendar = new GregorianCalendar();
calendar.setTime(date);
calendar.add(Calendar.DATE,t);
date=calendar.getTime();
Map<String,Object> detailMap = new HashMap<>();
detailMap.put("detail_no",t);
detailMap.put("plan_no",i);
detailMap.put("plan_time",format.format(date));
detailMap.put("plan_num", random.nextInt());
planDetails.add(detailMap);
}
}
//主表关系列
List<String> relationshipInMain = new LinkedList<>();
relationshipInMain.add("plan_no");
//附表关系列
List<String> relationshipInDetail = new LinkedList<>();
relationshipInDetail.add("plan_no");
try {
List<Map<String,Object>> datas = RowTransforColumn.rowTransforColumn(planMains,planDetails,relationshipInMain,relationshipInDetail,"plan_time","plan_num",null,null);
System.out.println(datas);
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
结果
转换前:
转换后: