oracle轉mysql過程當中的sum over處理

項目須要,原來的系統不少的統計分析,被要求把數據庫從oracle轉爲mysql,這是很坑的,mysql的統計分析比較弱,不少oracle有的函數,mysql沒有,須要千方百計改造或者編寫函數實現。java

在修改的過程當中,不少小的問題點都解決了,就剩下一個sum over的實現。sum over用來作統計總數很好用,免得再寫一遍或者嵌套一層。mysql

因爲代碼中的不少求總和的字段輸出的行數很少,最後考慮直接用java的反射機制來簡單實現oracle中sum over統計。代碼沒考慮太多通用性,只是根據本身的需求編寫的,實現以下:sql

package xx.xx.xx.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import xx.xx.xx.stat.vmodel.FlowSortData;

public class O2mUtils {

	private static final Logger logger = Logger.getLogger(Thread
            .currentThread().getStackTrace()[1].getClassName());
	
	private static String format = "%.0f";
	
	/**
	 * 設置保留2位小數,每次使用前調用,用完恢復
	 */
	public static void setFormat() {
		format = "%.2f";
	}
	
	private static void resetFormat() {
		format = "%.0f";
	}
	
	/**
	 * 獲取get方法、set方法
	 * @param o 獲取的類對象
	 * @param fieldFrom get字段名
	 * @param FieldTo set字段名
	 * @return
	 */
	private static Method[] getMethod(Object o, String ...strings) {
		int length = strings.length;
		Method[] methods = new Method[length];
		try {
			Class<?> clazz = o.getClass();
			Field fields[] = clazz.getDeclaredFields();
			for(Field f : fields) {
				if(f.getName().equals(strings[0])) {
					String fieldName = f.getName().substring(0, 1).toUpperCase() + f.getName().substring(1);
					methods[0] = clazz.getMethod("get" + fieldName);
				}
				if(f.getName().equals(strings[1])) {
					String fieldName = f.getName().substring(0, 1).toUpperCase() + f.getName().substring(1);
					Class<?> paramType = f.getType();
					methods[1] = clazz.getMethod("set" + fieldName, paramType);
				}
				if(length == 3 && f.getName().equals(strings[2])) {// 獲取get方法
					String fieldName = f.getName().substring(0, 1).toUpperCase() + f.getName().substring(1);
					methods[2] = clazz.getMethod("get" + fieldName);
				}
			}
		} catch (Exception e) {
			logger.error("反射獲取方法異常", e);
		}
		
		return methods;
	}
	
	/**
	 * oracle的sum over() 累加實現
	 * @param list 設置列表
	 * @param fieldFrom 累加字段
	 * @param fieldTo 累加和字段
	 */
	public static void sum_over(List<?> list, String fieldFrom, String fieldTo) {
		Method[] getField = getMethod(list.get(0), fieldFrom, fieldTo);
		if(getField != null && getField.length == 2) {
			try {
				Double total = 0.0;
				int i = 0;
				for(; i < list.size(); i++) {
					Double value = Double.valueOf(getField[0].invoke(list.get(i)).toString());
					total += value;
				}
				for(Object o : list) {
					getField[1].invoke(o, new Object[]{String.format(format, total)});
				}
			} catch (Exception e) {
				logger.error("取值、賦值異常", e);
			}
		}
		resetFormat();
	}
	
	/**
	 * oracle的sum over(order by) 累加實現
	 * @param list 設置列表
	 * @param fieldFrom 累加字段
	 * @param fieldTo 累加和字段
	 * @param reverse 正序反序
	 */
	public static void sum_over_order(List<?> list, String fieldFrom, String fieldTo, boolean reverse) {
		Method[] getField = getMethod(list.get(0), fieldFrom, fieldTo);
		if(getField != null && getField.length == 2) {
			try {
				int size = list.size();
				Double[] total = new Double[size];
				int i = 0, j = 0;
				for(; i < size; i++) {
					total[i] = 0.0;
				}
				if(reverse){
					for(i = 0; i < size; i++) {
						for(j = i; j < size; j++) {
							Double value = Double.valueOf(getField[0].invoke(list.get(i)).toString());
							total[j] += value;
						}
					}
				}else {
					for(i = size -1; i >= 0; i--) {
						for(j = i; j >= 0; j--) {
							Double value = Double.valueOf(getField[0].invoke(list.get(i)).toString());
							total[j] += value;
						}
					}
				}
				for(i = 0; i < size; i++) {
					getField[1].invoke(list.get(i), new Object[]{String.format(format, total[i])});
				}
			} catch (Exception e) {
				logger.error("取值、賦值異常", e);
			}
		}
		resetFormat();
	}
	
	/**
	 * oracle的sum over(partition by) 累加實現
	 * @param list 設置列表
	 * @param fieldPartition partition by 字段
	 * @param fieldFrom 累加字段
	 * @param fieldTo 累加和字段
	 */
	public static void sum_over_partition(List<?> list, String fieldPartition, String fieldFrom, String fieldTo) {
		Method[] getField = getMethod(list.get(0), fieldFrom, fieldTo, fieldPartition);
		if(getField != null && getField.length == 3) {
			try {
				int size = list.size();
				int i = 0, j = 0, strPos = 0;
				Double total = 0.0;
				String key = null;
				for(; i < size; i++) {
					if(key == null) {
						key = getField[2].invoke(list.get(i)).toString();
					}
					if(!getField[2].invoke(list.get(i)).toString().equals(key)) { // 遇到下一個累加
						for(j = strPos; j < i; j++) {
							getField[1].invoke(list.get(j), new Object[]{String.format(format, total)});
						}
						key = getField[2].invoke(list.get(i)).toString();
						total = 0.0;
						strPos = i;
					}
					Double value = Double.valueOf(getField[0].invoke(list.get(i)).toString());
					total += value;
				}
				for(j = strPos; j < i; j++) {
					getField[1].invoke(list.get(j), new Object[]{String.format(format, total)});
				}
			} catch (Exception e) {
				logger.error("取值、賦值異常", e);
			}
		}
		resetFormat();
	}
	
	public static void main(String[] args) {
		List<FlowSortData> list = new ArrayList<FlowSortData>();
		int i = 0;
		for(i = 0; i < 5; i++) {
			FlowSortData d = new FlowSortData();
			d.setNettype("1111");
			d.setFlow("100");
			list.add(d);
		}
		for(i = 0; i < 5; i++) {
			FlowSortData d = new FlowSortData();
			d.setNettype("2222");
			d.setFlow("150");
			list.add(d);
		}
		for(i = 0; i < 5; i++) {
			FlowSortData d = new FlowSortData();
			d.setNettype("3333");
			d.setFlow("50");
			list.add(d);
		}
//		O2mUtils.sum_over(list, "flow", "totalflow");
//		O2mUtils.sum_over_order(list, "flow", "totalflow", false);
		O2mUtils.setFormat();
		O2mUtils.sum_over_partition(list, "nettype", "flow", "totalflow");
		for(FlowSortData o : list) {
			System.out.println(o.getNettype() + " , " + o.getFlow() + " , " +o.getTotalflow());
		}
	}

}

package xx.xx.xx.stat.vmodel;

public class FlowSortData {

	private String nettype;
	private String flow;
	private String totalflow;
	public String getNettype() {
		return nettype;
	}
	public void setNettype(String nettype) {
		this.nettype = nettype;
	}
	public String getFlow() {
		return flow;
	}
	public void setFlow(String flow) {
		this.flow = flow;
	}
	public String getTotalflow() {
		return totalflow;
	}
	public void setTotalflow(String totalflow) {
		this.totalflow = totalflow;
	}
}


  那時候用的是jdk1.6,如今能夠考慮用java 8的stream來實現。數據庫

相關文章
相關標籤/搜索