使用java从mssql表中检索直方图

时间:2017-08-14 09:00:27

标签: java sql sql-server optimization query-optimization

我想实现可以连接到任何sql server并从中加载任何表的java应用程序。对于每个表,我想基于一些任意列创建直方图。

例如,如果我有这张表

name   profit
------------
name1   12
name2   14
name3   18
name4   13

我可以根据利润列的最小值和最大值创建bin大小为4的直方图,并计算每个bin的记录数。

结果是:

profit    count
---------------
12-16     3
16-20     1

我遇到此问题的解决方案是根据所需的列检索所有数据,之后使用java stream Collectors.groupingBy按记录构建bin和group。

我不确定我的解决方案是否已经过优化,为此我需要一些帮助才能找到更好的算法,特别是当我有大量记录时。(例如使用sql server或其他框架的一些好处,可以使用。)

我可以针对此问题使用更好的算法吗?

编辑1: 假设我的sql结果在列表数据

private String mySimpleHash(Object[] row, int index) {
        StringBuilder hash = new StringBuilder();
        for (int i = 0; i < row.length; i++)
            if (i != index)
                hash.append(row[i]).append(":");
        return hash.toString();
    }
 //index is index of column for histogram
List<Object[]> histogramData = new ArrayList<>();
final Map<String, List<Object[]>> map = data.stream().collect(
                Collectors.groupingBy(row -> mySimpleHash(Arrays.copyOfRange(row, index))));
for (final Map.Entry<String, List<Object[]>> entry : map.entrySet()) {
   Object[] newRow = newData.get(rowNum); 
   double result = entry.getValue().stream()
                                .mapToDouble(row -> 
   Double.valueOf(row[index].toString())).count();
   newRow[index] = result;
   histogramData.add(newRow);
}

1 个答案:

答案 0 :(得分:1)

正如您所考虑的那样,如果表中的行数增加,则在从SQL服务器获取所有数据后执行聚合将非常昂贵。您可以在SQL中简单地进行聚合。

根据您表达柱状图箱的方式,这可能是微不足道的,也可能需要一些工作。在您的情况下,最低bin以min值开始的​​要求需要一些设置,而不是从0开始的binning。请参阅下面的示例。内部查询是将值映射到bin编号,外部查询是聚合和计算bin边界。

CREATE TABLE Test (
    Name varchar(max) NOT NULL,
    Profit int NOT NULL
)

INSERT Test(Name, Profit)
VALUES
('name1', 12),
('name2', 14),
('name3', 18),
('name4', 13)

DECLARE @minValue int = (SELECT MIN(Profit) FROM Test)
DECLARE @binSize int = 4

SELECT
    (@minValue + @binSize * Bin) AS BinLow,
    (@minValue + @binSize * Bin) + @binSize - 1 AS BinHigh,
    COUNT(*) AS Count
FROM (
    SELECT
    ((Profit - @minValue) / @binSize) AS Bin
    FROM
    Test
) AS t
GROUP BY Bin


| BinLow | BinHigh | Count |
|--------|---------|-------|
|     12 |      15 |     3 |
|     16 |      19 |     1 |

http://sqlfiddle.com/#!18/d093c/9