提交 7e41b46e authored 作者: Thomas Mueller's avatar Thomas Mueller

New aggregate function HISTOGRAM to calculate the histogram.

上级 d982a975
......@@ -111,6 +111,11 @@ public class Aggregate extends Expression {
*/
static final int SELECTIVITY = 13;
/**
* The aggregate type for HISTOGRAM(expression).
*/
static final int HISTOGRAM = 14;
private static final HashMap<String, Integer> AGGREGATES = New.hashMap();
private final int type;
......@@ -158,12 +163,13 @@ public class Aggregate extends Expression {
addAggregate("VAR", VAR_SAMP);
addAggregate("VARIANCE", VAR_SAMP);
addAggregate("BOOL_OR", BOOL_OR);
// HSQLDB compatibility, but conflicts with >EVERY(...)
// HSQLDB compatibility, but conflicts with x > EVERY(...)
addAggregate("SOME", BOOL_OR);
addAggregate("BOOL_AND", BOOL_AND);
// HSQLDB compatibility, but conflicts with >SOME(...)
// HSQLDB compatibility, but conflicts with x > SOME(...)
addAggregate("EVERY", BOOL_AND);
addAggregate("SELECTIVITY", SELECTIVITY);
addAggregate("HISTOGRAM", HISTOGRAM);
}
private static void addAggregate(String name, int type) {
......@@ -367,8 +373,7 @@ public class Aggregate extends Expression {
case GROUP_CONCAT:
dataType = Value.STRING;
scale = 0;
precision = Integer.MAX_VALUE;
displaySize = Integer.MAX_VALUE;
precision = displaySize = Integer.MAX_VALUE;
break;
case COUNT_ALL:
case COUNT:
......@@ -383,6 +388,11 @@ public class Aggregate extends Expression {
precision = ValueInt.PRECISION;
displaySize = ValueInt.DISPLAY_SIZE;
break;
case HISTOGRAM:
dataType = Value.ARRAY;
scale = 0;
precision = displaySize = Integer.MAX_VALUE;
break;
case SUM:
if (!DataType.supportsAdd(dataType)) {
throw DbException.get(ErrorCode.SUM_OR_AVG_ON_WRONG_DATATYPE_1, getSQL());
......@@ -477,6 +487,9 @@ public class Aggregate extends Expression {
case SELECTIVITY:
text = "SELECTIVITY";
break;
case HISTOGRAM:
text = "HISTOGRAM";
break;
case SUM:
text = "SUM";
break;
......
......@@ -7,14 +7,18 @@
package org.h2.expression;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.message.DbException;
import org.h2.util.IntIntHashMap;
import org.h2.util.New;
import org.h2.util.ValueHashMap;
import org.h2.value.CompareMode;
import org.h2.value.DataType;
import org.h2.value.Value;
import org.h2.value.ValueArray;
import org.h2.value.ValueBoolean;
import org.h2.value.ValueDouble;
import org.h2.value.ValueInt;
......@@ -61,10 +65,24 @@ class AggregateData {
// the value -1 is not supported
distinctHashes.put(hash, 1);
return;
}
if (aggregateType == Aggregate.COUNT_ALL) {
} else if (aggregateType == Aggregate.COUNT_ALL) {
count++;
return;
} else if (aggregateType == Aggregate.HISTOGRAM) {
if (distinctValues == null) {
distinctValues = ValueHashMap.newInstance();
}
AggregateData a = distinctValues.get(v);
if (a == null) {
if (distinctValues.size() < Constants.SELECTIVITY_DISTINCT_COUNT) {
a = new AggregateData(Aggregate.HISTOGRAM, dataType);
distinctValues.put(v, a);
}
}
if (a != null) {
a.count++;
}
return;
}
if (v == ValueNull.INSTANCE) {
return;
......@@ -79,6 +97,7 @@ class AggregateData {
}
switch (aggregateType) {
case Aggregate.COUNT:
case Aggregate.HISTOGRAM:
return;
case Aggregate.SUM:
if (value == null) {
......@@ -229,6 +248,24 @@ class AggregateData {
v = ValueDouble.get(m2 / (count - 1));
break;
}
case Aggregate.HISTOGRAM:
ValueArray[] values = new ValueArray[distinctValues.size()];
int i = 0;
for (Value dv : distinctValues.keys()) {
AggregateData d = distinctValues.get(dv);
values[i] = ValueArray.get(new Value[] {dv, ValueLong.get(d.count)});
i++;
}
final CompareMode compareMode = database.getCompareMode();
Arrays.sort(values, new Comparator<ValueArray>() {
public int compare(ValueArray v1, ValueArray v2) {
Value a1 = v1.getList()[0];
Value a2 = v2.getList()[0];
return a1.compareTo(a2, compareMode);
}
});
v = ValueArray.get(values);
break;
default:
DbException.throwInternalError("type=" + aggregateType);
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论