【问题标题】:retrieve histogram from mssql table using java使用java从mssql表中检索直方图
【发布时间】:2018-01-22 01:53:28
【问题描述】:

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

例如,如果我有这张桌子

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

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

结果是:

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

我对这个问题的解决方案是根据所需列检索所有数据,然后使用 java 流 Collectors.groupingBy 按记录构造 bin 和分组。

我不确定我的解决方案是否经过优化,为此我需要一些帮助来找到更好的算法,特别是当我有大量记录时。(例如使用 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);
}

【问题讨论】:

  • 你有代码吗?
  • 是的,我添加一个简单的。

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


【解决方案1】:

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

根据您如何表达直方图箱,这要么是微不足道的,要么需要一些工作。在您的情况下,最低 bin 从最小值开始的要求需要一些设置,而不是从 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多