func buildSelectGroupByResult(p *SelectPlan, r *mysql.Result) error {
	resultMap := make(map[string]ResultRow)
	resultFieldLength := len(r.Fields)
	originColumnCount := p.GetColumnCount()
	deltaColumnCount := resultFieldLength - originColumnCount
	for i, v := range r.Values {
		keySlice := make([]interface{}, 0)
		for _, index := range p.GetGroupByColumnInfo() {
			keySlice = append(keySlice, v[index+deltaColumnCount])
		}
		mk, err := generateMapKey(keySlice)
		if err != nil {
			return err
		}
		_, ok := resultMap[mk]
		if !ok {
			resultMap[mk] = ResultRow(r.Values[i])
			continue
		}
		if len(p.aggregateFuncs) == 0 {
			continue
		}
		retToMerge := ResultRow(r.Values[i])
		for _, mfunc := range p.aggregateFuncs {
			if err := mfunc.MergeTo(retToMerge, resultMap[mk]); err != nil {
				return fmt.Errorf("MergeTo error, func: %v, value: %v, err: %v", mfunc, retToMerge, err)
			}
		}
	}
	err := buildResultFromResultMap(r, resultMap)
	if err != nil {
		return fmt.Errorf("buildResultFromResultMap error: %v", err)
	}
	return nil
}
contains mergeGroupByWithoutFunc() and mergeGroupByWithFunc()
package plan
import (
	"fmt"
	"strconv"
	"strings"
	"github.com/XiaoMi/Gaea/mysql"
	"github.com/XiaoMi/Gaea/parser/ast"
	"github.com/XiaoMi/Gaea/util/hack"
	"github.com/XiaoMi/Gaea/util/math"
)
type ResultRow []interface{}
func (r ResultRow) GetInt(column int) (int64, error) {
	d := r[column]
	switch v := d.(type) {
	case uint64:
		return int64(v), nil
	case int64:
		return v, nil
	case float64:
		return int64(v), nil
	case string:
		return strconv.ParseInt(v, 10, 64)
	case []byte:
		return strconv.ParseInt(string(v), 10, 64)
	case nil:
		return 0, nil
	default:
		return 0, fmt.Errorf("data type is %T", v)
	}
}
func (r ResultRow) GetUint(column int) (uint64, error) {
	d := r[column]
	switch v := d.(type) {
	case uint64:
		return v, nil
	case int64:
		return uint64(v), nil
	case float64:
		return uint64(v), nil
	case string:
		return strconv.ParseUint(v, 10, 64)
	case []byte:
		return strconv.ParseUint(string(v), 10, 64)
	case nil:
		return 0, nil
	default:
		return 0, fmt.Errorf("data type is %T", v)
	}
}
func (r ResultRow) GetFloat(column int) (float64, error) {
	d := r[column]
	switch v := d.(type) {
	case float64:
		return v, nil
	case uint64:
		return float64(v), nil
	case int64:
		return float64(v), nil
	case string:
		return strconv.ParseFloat(v, 64)
	case []byte:
		return strconv.ParseFloat(string(v), 64)
	case nil:
		return 0, nil
	default:
		return 0, fmt.Errorf("data type is %T", v)
	}
}
func (r ResultRow) SetValue(column int, value interface{}) {
	r[column] = value
}
func (r ResultRow) GetValue(column int) interface{} {
	return r[column]
}
type AggregateFuncMerger interface {
	MergeTo(from, to ResultRow) error
}
type aggregateFuncBaseMerger struct {
	fieldIndex int  
}
func CreateAggregateFunctionMerger(funcType string, fieldIndex int) (AggregateFuncMerger, error) {
	switch strings.ToLower(funcType) {
	case "count":
		ret := new(AggregateFuncCountMerger)
		ret.fieldIndex = fieldIndex
		return ret, nil
	case "sum":
		ret := new(AggregateFuncSumMerger)
		ret.fieldIndex = fieldIndex
		return ret, nil
	case "max":
		ret := new(AggregateFuncMaxMerger)
		ret.fieldIndex = fieldIndex
		return ret, nil
	case "min":
		ret := new(AggregateFuncMinMerger)
		ret.fieldIndex = fieldIndex
		return ret, nil
	default:
		return nil, fmt.Errorf("aggregate function type is not support: %s", funcType)
	}
}
type AggregateFuncCountMerger struct {
	aggregateFuncBaseMerger
}
func (a *AggregateFuncCountMerger) MergeTo(from, to ResultRow) error {
	idx := a.fieldIndex
	if idx >= len(from) || idx >= len(to) {
		return fmt.Errorf("field index out of bound: %d", a.fieldIndex)
	}
	valueToMerge, err := from.GetInt(idx)
	if err != nil {
		return fmt.Errorf("get from int value error: %v", err)
	}
	originValue, err := to.GetInt(idx)
	if err != nil {
		return fmt.Errorf("get to int value error: %v", err)
	}
	to.SetValue(idx, originValue+valueToMerge)
	return nil
}
type AggregateFuncSumMerger struct {
	aggregateFuncBaseMerger
}
func (a *AggregateFuncSumMerger) MergeTo(from, to ResultRow) error {
	idx := a.fieldIndex
	if idx >= len(from) || idx >= len(to) {
		return fmt.Errorf("field index out of bound: %d", a.fieldIndex)
	}
	fromValueI := from.GetValue(idx)
	if fromValueI == nil {
		return nil
	}
	switch to.GetValue(idx).(type) {
	case int64:
		return a.sumToInt64(from, to)
	case uint64:
		return a.sumToUint64(from, to)
	case float64, string, []byte, nil:
		return a.sumToFloat64(from, to)
	default:
		fromValue := from.GetValue(idx)
		toValue := to.GetValue(idx)
		return fmt.Errorf("cannot sum value %v (%T) to %v (%T)", fromValue, fromValue, toValue, toValue)
	}
}
func (a *AggregateFuncSumMerger) sumToInt64(from, to ResultRow) error {
	idx := a.fieldIndex  
	valueToMerge, err := from.GetInt(idx)
	if err != nil {
		return fmt.Errorf("get from int value error: %v", err)
	}
	originValue, err := to.GetInt(idx)
	if err != nil {
		return fmt.Errorf("get to int value error: %v", err)
	}
	to.SetValue(idx, originValue+valueToMerge)
	return nil
}
func (a *AggregateFuncSumMerger) sumToUint64(from, to ResultRow) error {
	idx := a.fieldIndex  
	valueToMerge, err := from.GetUint(idx)
	if err != nil {
		return fmt.Errorf("get from int value error: %v", err)
	}
	originValue, err := to.GetUint(idx)
	if err != nil {
		return fmt.Errorf("get to int value error: %v", err)
	}
	to.SetValue(idx, originValue+valueToMerge)
	return nil
}
func (a *AggregateFuncSumMerger) sumToFloat64(from, to ResultRow) error {
	idx := a.fieldIndex  
	valueToMerge, err := from.GetFloat(idx)
	if err != nil {
		return fmt.Errorf("get from int value error: %v", err)
	}
	originValue, err := to.GetFloat(idx)
	if err != nil {
		return fmt.Errorf("get to int value error: %v", err)
	}
	to.SetValue(idx, originValue+valueToMerge)
	return nil
}
type AggregateFuncMaxMerger struct {
	aggregateFuncBaseMerger
}
func (a *AggregateFuncMaxMerger) MergeTo(from, to ResultRow) error {
	idx := a.fieldIndex
	if idx >= len(from) || idx >= len(to) {
		return fmt.Errorf("field index out of bound: %d", a.fieldIndex)
	}
	fromValueI := from.GetValue(idx)
	toValueI := to.GetValue(idx)
	if fromValueI == nil {
		return nil
	}
	switch toValue := toValueI.(type) {
	case nil:
		to.SetValue(idx, fromValueI)
		return nil
	case int64:
		if fromValueI.(int64) > toValue {
			to.SetValue(idx, fromValueI)
		}
		return nil
	case uint64:
		if fromValueI.(uint64) > toValue {
			to.SetValue(idx, fromValueI)
		}
		return nil
	case float64:
		if fromValueI.(float64) > toValue {
			to.SetValue(idx, fromValueI)
		}
		return nil
	case string:
		if fromValueI.(string) > toValue {
			to.SetValue(idx, fromValueI)
		}
		return nil
	default:
		return fmt.Errorf("cannot compare value %v (%T) to %v (%T)", fromValueI, fromValueI, toValueI, toValueI)
	}
}
type AggregateFuncMinMerger struct {
	aggregateFuncBaseMerger
}
func (a *AggregateFuncMinMerger) MergeTo(from, to ResultRow) error {
	idx := a.fieldIndex
	if idx >= len(from) || idx >= len(to) {
		return fmt.Errorf("field index out of bound: %d", a.fieldIndex)
	}
	fromValueI := from.GetValue(idx)
	toValueI := to.GetValue(idx)
	if fromValueI == nil {
		return nil
	}
	switch toValue := toValueI.(type) {
	case nil:
		to.SetValue(idx, fromValueI)
		return nil
	case int64:
		if fromValueI.(int64) < toValue {
			to.SetValue(idx, fromValueI)
		}
		return nil
	case uint64:
		if fromValueI.(uint64) < toValue {
			to.SetValue(idx, fromValueI)
		}
		return nil
	case float64:
		if fromValueI.(float64) < toValue {
			to.SetValue(idx, fromValueI)
		}
		return nil
	case string:
		if fromValueI.(string) < toValue {
			to.SetValue(idx, fromValueI)
		}
		return nil
	default:
		return fmt.Errorf("cannot compare value %v (%T) to %v (%T)", fromValueI, fromValueI, toValueI, toValueI)
	}
}
func MergeExecResult(rs []*mysql.Result) (*mysql.Result, error) {
	r := new(mysql.Result)
	for _, v := range rs {
		r.Status |= v.Status
		r.AffectedRows += v.AffectedRows
		if r.InsertID == 0 {
			r.InsertID = v.InsertID
		} else if v.InsertID != 0 && r.InsertID > v.InsertID {
			r.InsertID = v.InsertID
		}
	}
	return r, nil
}
func MergeSelectResult(p *SelectPlan, stmt *ast.SelectStmt, rs []*mysql.Result) (*mysql.Result, error) {
	ret := mergeMultiResultSet(rs)
	if p.distinct {
		if err := removeDistinctRowInResult(p, ret); err != nil {
			return nil, err
		}
	}
	if stmt.GroupBy != nil {
		if err := buildSelectGroupByResult(p, ret); err != nil {
			return nil, err
		}
	} else {
		if err := buildSelectOnlyResult(p, ret); err != nil {
			return nil, err
		}
	}
	if err := sortSelectResult(p, stmt, ret); err != nil {
		return nil, err
	}
	if err := limitSelectResult(p, ret); err != nil {
		return nil, err
	}
	if err := trimExtraFields(p, ret); err != nil {
		return nil, fmt.Errorf("trimExtraFields error: %v", err)
	}
	if err := GenerateSelectResultRowData(ret); err != nil {
		return nil, fmt.Errorf("generate RowData error: %v", err)
	}
	return ret, nil
}
func mergeMultiResultSet(rs []*mysql.Result) *mysql.Result {
	if len(rs) == 1 {
		return rs[0]
	}
	for i := 1; i < len(rs); i++ {
		rs[0].Status |= rs[i].Status
		rs[0].Values = append(rs[0].Values, rs[i].Values...)
		rs[0].RowDatas = append(rs[0].RowDatas, rs[i].RowDatas...)
	}
	return rs[0]
}
func removeDistinctRowInResult(p *SelectPlan, r *mysql.Result) error {
	distinctKeySet := make(map[string]bool)
	var rowToRemove []int
	resultFieldLength := len(r.Fields)
	originColumnCount := p.GetColumnCount()
	deltaColumnCount := resultFieldLength - originColumnCount
	colCnt := p.originColumnCount + deltaColumnCount
	rowCount := len(r.Values)
	for i := 0; i < rowCount; i++ {
		keySlice := r.Values[i][0:colCnt]
		mk, err := generateMapKey(keySlice)
		if err != nil {
			return err
		}
		_, ok := distinctKeySet[mk]
		if !ok {
			distinctKeySet[mk] = true
		} else {
			rowToRemove = append(rowToRemove, i)
		}
	}
	rowToRemoveCnt := len(rowToRemove)
	if rowToRemoveCnt == 0 {
		return nil
	}
	originRows := r.Values
	r.RowDatas = nil
	r.Values = originRows[:0]
	var j int
	for i := 0; i < rowCount; i++ {
		if j == rowToRemoveCnt {
			r.Values = append(r.Values, originRows[i:]...)
			break
		}
		if i == rowToRemove[j] {
			j++
		} else {
			r.Values = append(r.Values, originRows[i])
		}
	}
	return nil
}