/** * Add a value to this aggregate. * * @param database the database * @param distinct if the calculation should be distinct * @param v the value */ void add(Database database, boolean distinct, Value v) { if (aggregateType == Aggregate.SELECTIVITY) { count++; if (distinctHashes == null) { distinctHashes = new IntIntHashMap(); } int size = distinctHashes.size(); if (size > Constants.SELECTIVITY_DISTINCT_COUNT) { distinctHashes = new IntIntHashMap(); m2 += size; } int hash = v.hashCode(); // the value -1 is not supported distinctHashes.put(hash, 1); return; } 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; } count++; if (distinct) { if (distinctValues == null) { distinctValues = ValueHashMap.newInstance(); } distinctValues.put(v, this); return; } switch (aggregateType) { case Aggregate.COUNT: case Aggregate.HISTOGRAM: return; case Aggregate.SUM: if (value == null) { value = v.convertTo(dataType); } else { v = v.convertTo(value.getType()); value = value.add(v); } break; case Aggregate.AVG: if (value == null) { value = v.convertTo(DataType.getAddProofType(dataType)); } else { v = v.convertTo(value.getType()); value = value.add(v); } break; case Aggregate.MIN: if (value == null || database.compare(v, value) < 0) { value = v; } break; case Aggregate.MAX: if (value == null || database.compare(v, value) > 0) { value = v; } break; case Aggregate.GROUP_CONCAT: { if (list == null) { list = New.arrayList(); } list.add(v); break; } case Aggregate.STDDEV_POP: case Aggregate.STDDEV_SAMP: case Aggregate.VAR_POP: case Aggregate.VAR_SAMP: { // Using Welford's method, see also // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance // http://www.johndcook.com/standard_deviation.html double x = v.getDouble(); if (count == 1) { mean = x; m2 = 0; } else { double delta = x - mean; mean += delta / count; m2 += delta * (x - mean); } break; } case Aggregate.BOOL_AND: v = v.convertTo(Value.BOOLEAN); if (value == null) { value = v; } else { value = ValueBoolean.get(value.getBoolean().booleanValue() && v.getBoolean().booleanValue()); } break; case Aggregate.BOOL_OR: v = v.convertTo(Value.BOOLEAN); if (value == null) { value = v; } else { value = ValueBoolean.get(value.getBoolean().booleanValue() || v.getBoolean().booleanValue()); } break; default: DbException.throwInternalError("type=" + aggregateType); } }
void merge(Database database, boolean distinct, Value v) { if (aggregateType == Aggregate.COUNT || aggregateType == Aggregate.COUNT_ALL) { count += v.getLong(); 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; } count++; if (distinct) { if (distinctValues == null) { distinctValues = ValueHashMap.newInstance(); } distinctValues.put(v, this); return; } switch (aggregateType) { case Aggregate.COUNT: case Aggregate.HISTOGRAM: return; case Aggregate.SUM: case Aggregate.SELECTIVITY: if (value == null) { value = v.convertTo(dataType); } else { v = v.convertTo(value.getType()); value = value.add(v); } break; case Aggregate.AVG: if (value == null) { value = v.convertTo(DataType.getAddProofType(dataType)); } else { // AVG聚合函数merge的次数不会超过1 DbException.throwInternalError("type=" + aggregateType); } break; case Aggregate.MIN: if (value == null || database.compare(v, value) < 0) { value = v; } break; case Aggregate.MAX: if (value == null || database.compare(v, value) > 0) { value = v; } break; case Aggregate.GROUP_CONCAT: { if (list == null) { list = New.arrayList(); } list.add(v); break; } case Aggregate.STDDEV_POP: case Aggregate.STDDEV_SAMP: case Aggregate.VAR_POP: case Aggregate.VAR_SAMP: { v = v.convertTo(Value.DOUBLE); if (value == null) { value = v; } else { // 这4种聚合函数merge的次数不会超过1 DbException.throwInternalError("type=" + aggregateType); } break; } case Aggregate.BOOL_AND: v = v.convertTo(Value.BOOLEAN); if (value == null) { value = v; } else { value = ValueBoolean.get(value.getBoolean().booleanValue() && v.getBoolean().booleanValue()); } break; case Aggregate.BOOL_OR: v = v.convertTo(Value.BOOLEAN); if (value == null) { value = v; } else { value = ValueBoolean.get(value.getBoolean().booleanValue() || v.getBoolean().booleanValue()); } break; default: DbException.throwInternalError("type=" + aggregateType); } }