在Java中用Rollup模拟Group

时间:2014-08-14 07:23:19

标签: java sql java-8

我有ArrayList<Map<String, Object>>,其数据类似于数据库表。我想用自己的Java来计算Subtotal总成员数。 GroupBY Rollup / Cube可以在SQL中实现相同的功能。 我写了一个函数来计算GroupBy Cube。

public static List<Map<String, Object>> applyGroupBy(List<LevelDetail> dimensionColumns, List<MeasureDetail> numericColumns, List<Map<String, Object>> resultset) {
    List<Map<String, Object>> resultsetNew = new ArrayList<Map<String, Object>>();
    Map<String, List<Double>> grandTotalMap = new HashMap<String, List<Double>>();
    for (LevelDetail levelDetail : dimensionColumns) {
        Stream<Map<String, Object>> stream = resultset.stream();
        stream.collect(Collectors.groupingBy(m -> m.get(levelDetail.getName()), LinkedHashMap::new, Collectors.mapping(m -> m, Collectors.toList()))).forEach((g, r) -> {
            Map<String, Object> row = new HashMap<String, Object>();
            row.put(levelDetail.getName(), g);
            for (MeasureDetail measureDetail : numericColumns) {
                DoubleStream valueStream = r.stream().mapToDouble(p -> {
                    p.put(levelDetail.getName() + "_nb_grouping", 0);
                    resultsetNew.add(p);
                    return Double.parseDouble(p.get(measureDetail.getName()) != null ? p.get(measureDetail.getName()).toString() : "0");
                });
                Double value = getAggregatedResult(valueStream, measureDetail.getMeasure_rollup_expr());
                row.put(measureDetail.getName(), value);
                if (dimensionColumns.indexOf(levelDetail) == 0) {
                    if (!grandTotalMap.containsKey(measureDetail.getName())) {
                        grandTotalMap.put(measureDetail.getName(), new ArrayList<Double>());
                    }
                    grandTotalMap.get(measureDetail.getName()).add(value);
                }
            }
            row.put(levelDetail.getName() + "_nb_grouping", 0);
            for (LevelDetail ld : dimensionColumns) {
                if (!ld.getName().equals(levelDetail.getName())) {
                    row.put(ld.getName() + "_nb_grouping", 1);
                    row.put(ld.getName(), null);
                }
            }
            resultsetNew.add(row);
        });
    }
    Map<String, Object> row = new HashMap<String, Object>();
    for (LevelDetail levelDetail : dimensionColumns) {
        row.put(levelDetail.getName(), null);
        row.put(levelDetail.getName() + "_nb_grouping", 1);
    }
    for (MeasureDetail measureDetail : numericColumns) {
        Double value = getAggregatedResult(grandTotalMap.get(measureDetail.getName()).stream().mapToDouble((i) -> (Double) i), measureDetail.getMeasure_rollup_expr());
        row.put(measureDetail.getName(), value);
    }
    resultsetNew.add(row);
    resultset = new ArrayList<Map<String, Object>>(new LinkedHashSet<Map<String, Object>>(resultsetNew));
    resultsetNew.clear();
    resultsetNew.addAll(resultset);
    return resultsetNew;
}

private static final String AVG = "avg";
private static final String MIN = "min";
private static final String MAX = "max";

private static Double getAggregatedResult(DoubleStream ds, String agg) {
    switch (agg.toLowerCase()) {
    case AVG:
        return ds.average().getAsDouble();
    case MIN:
        ds.min().getAsDouble();
    case MAX:
        ds.max().getAsDouble();
    default:
        return ds.sum();
    }
}

我想写一个由Rollup分组的方法。无论是按Rollup还是Cube分组,它都可以参数化为相同的函数。

1 个答案:

答案 0 :(得分:0)

使用免费软件SGBD时,它们不像商业软件那样强大,有时必须在Java代码中实现某些功能。汇总似乎是多维数据集查询的子集。因此,要获得汇总,您必须从多维数据集查询和一些部分总计中删除一些行。在一个具体的情况下,这可能相当容易,但概括它可能需要一些时间来确切地发现应该删除哪些行以及哪种算法可以在每种情况下执行它。