@Override Value getMergedValue(Database database, int dataType, boolean distinct) { if (distinct) { count = 0; groupDistinct(database, dataType); } Value v = null; switch (aggregateType) { case Aggregate.SUM: case Aggregate.MIN: case Aggregate.MAX: case Aggregate.BOOL_AND: case Aggregate.BOOL_OR: case Aggregate.BIT_AND: case Aggregate.BIT_OR: v = value; break; case Aggregate.AVG: case Aggregate.STDDEV_POP: case Aggregate.STDDEV_SAMP: case Aggregate.VAR_POP: case Aggregate.VAR_SAMP: default: DbException.throwInternalError("type=" + aggregateType); } return v == null ? ValueNull.INSTANCE : v.convertTo(dataType); }
@Override Value getValue(Database database, int dataType, boolean distinct) { if (distinct) { count = 0; groupDistinct(database, dataType); } Value v = null; switch (aggregateType) { case Aggregate.SUM: case Aggregate.MIN: case Aggregate.MAX: case Aggregate.BIT_OR: case Aggregate.BIT_AND: case Aggregate.BOOL_OR: case Aggregate.BOOL_AND: v = value; break; case Aggregate.AVG: if (value != null) { v = Aggregate.divide(value, count); } break; case Aggregate.STDDEV_POP: { if (count < 1) { return ValueNull.INSTANCE; } v = ValueDouble.get(Math.sqrt(m2 / count)); break; } case Aggregate.STDDEV_SAMP: { if (count < 2) { return ValueNull.INSTANCE; } v = ValueDouble.get(Math.sqrt(m2 / (count - 1))); break; } case Aggregate.VAR_POP: { if (count < 1) { return ValueNull.INSTANCE; } v = ValueDouble.get(m2 / count); break; } case Aggregate.VAR_SAMP: { if (count < 2) { return ValueNull.INSTANCE; } v = ValueDouble.get(m2 / (count - 1)); break; } default: DbException.throwInternalError("type=" + aggregateType); } return v == null ? ValueNull.INSTANCE : v.convertTo(dataType); }
@Override void add(Database database, int dataType, boolean distinct, Value v) { if (v == ValueNull.INSTANCE) { return; } count++; if (distinct) { if (distinctValues == null) { distinctValues = ValueHashMap.newInstance(); } distinctValues.put(v, this); return; } switch (aggregateType) { 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.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; case Aggregate.BIT_AND: if (value == null) { value = v.convertTo(dataType); } else { value = ValueLong.get(value.getLong() & v.getLong()).convertTo(dataType); } break; case Aggregate.BIT_OR: if (value == null) { value = v.convertTo(dataType); } else { value = ValueLong.get(value.getLong() | v.getLong()).convertTo(dataType); } break; default: DbException.throwInternalError("type=" + aggregateType); } }
@Override void merge(Database database, int dataType, boolean distinct, Value v) { if (v == ValueNull.INSTANCE) { return; } count++; if (distinct) { if (distinctValues == null) { distinctValues = ValueHashMap.newInstance(); } distinctValues.put(v, this); return; } switch (aggregateType) { case Aggregate.SUM: if (value == null) { value = v.convertTo(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.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; case Aggregate.BIT_AND: if (value == null) { value = v.convertTo(dataType); } else { value = ValueLong.get(value.getLong() & v.getLong()).convertTo(dataType); } break; case Aggregate.BIT_OR: if (value == null) { value = v.convertTo(dataType); } else { value = ValueLong.get(value.getLong() | v.getLong()).convertTo(dataType); } break; // 这5个在分布式环境下会进行重写,所以合并时是不会出现的 case Aggregate.AVG: case Aggregate.STDDEV_POP: case Aggregate.STDDEV_SAMP: case Aggregate.VAR_POP: case Aggregate.VAR_SAMP: default: DbException.throwInternalError("type=" + aggregateType); } }