【问题标题】:Simulate Groupby Rollup in Java在 Java 中通过汇总模拟分组
【发布时间】:2014-10-07 18:20:31
【问题描述】:

我有一个ArrayList<Map<String, Object>>,其中包含数据库表等数据。我想自己计算 Java 中的成员总数。 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 分组,都可以将其参数化为相同的功能。

【问题讨论】:

  • 如果 SQL 是您的灵感来源,那么您真的应该考虑通过 GROUPING SETS 推广 ROLLUPCUBE。这可能还会简化您的广义算法...
  • 您在minmax 聚合中缺少return,并且将返回sum

标签: java sql java-8


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2011-05-02
    • 2018-12-04
    • 2012-01-28
    • 1970-01-01
    • 1970-01-01
    • 2014-04-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-03
    相关资源
    最近更新 更多