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