vitessio/vitess · error

group by expression does not reference an alias in the selec

Error message

group by expression does not reference an alias in the select list: %v

What it means

Every GROUP BY column must match an alias defined in the SELECT list of a vreplication table plan. findCol looks up the group-by column among tpb.colExprs; if not found, the builder cannot correlate the grouping with what is being materialized and errors out.

Source

Thrown at go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go:561

func (tpb *tablePlanBuilder) addCol(ident sqlparser.IdentifierCI) {
	tpb.sendSelect.AddSelectExpr(&sqlparser.AliasedExpr{
		Expr: &sqlparser.ColName{Name: ident},
	})
}

func (tpb *tablePlanBuilder) analyzeGroupBy(groupBy *sqlparser.GroupBy) error {
	if groupBy == nil {
		// If there's no grouping, the it's an insertNormal.
		return nil
	}
	for _, expr := range groupBy.Exprs {
		colname, ok := expr.(*sqlparser.ColName)
		if !ok {
			return fmt.Errorf("unsupported non-column name or alias in group by clause: %v", sqlparser.String(expr))
		}
		cexpr := tpb.findCol(colname.Name)
		if cexpr == nil {
			return fmt.Errorf("group by expression does not reference an alias in the select list: %v", sqlparser.String(expr))
		}
		if cexpr.operation != opExpr {
			return fmt.Errorf("group by expression is not allowed to reference an aggregate expression: %v", sqlparser.String(expr))
		}
		cexpr.isGrouped = true
	}
	// If all colExprs are grouped, then it's an insertIgnore.
	tpb.onInsert = insertIgnore
	for _, cExpr := range tpb.colExprs {
		if !cExpr.isGrouped {
			// If some colExprs are not grouped, then it's an insertOnDup.
			tpb.onInsert = insertOnDup
			break
		}
	}
	return nil
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Add the grouping column to the SELECT list with an alias matching the GROUP BY name.
  2. Ensure the GROUP BY name exactly matches the select-list alias/column name.
  3. Remember the supported pattern: SELECT <groupcol>, <aggregates> ... GROUP BY <groupcol>.

Example fix

// before
select sum(x) as s from t group by y
// after
select y, sum(x) as s from t group by y
Defensive patterns

Strategy: validation

Validate before calling

// Require every GROUP BY name to appear as a select-list column alias
func groupByInSelectList(sel *sqlparser.Select) bool {
    names := map[string]bool{}
    for _, e := range sel.SelectExprs {
        if ae, ok := e.(*sqlparser.AliasedExpr); ok {
            if c, ok := ae.Expr.(*sqlparser.ColName); ok {
                n := ae.As.String(); if n == "" { n = c.Name.String() }
                names[n] = true
            }
        }
    }
    for _, e := range sel.GroupBy.Exprs {
        c, ok := e.(*sqlparser.ColName)
        if !ok || !names[c.Name.String()] { return false }
    }
    return true
}

Type guard

func groupColSelected(c *sqlparser.ColName, names map[string]bool) bool { return names[c.Name.String()] }

Prevention

When it happens

Trigger: Materialize/vreplication SELECT ... GROUP BY col where col is not one of the (aliased) select-list items, e.g. SELECT sum(x) AS s FROM t GROUP BY y; analyzeGroupBy's findCol(y) returns nil.

Common situations: Users grouping by a column they forgot to select; queries where the group-by column has a different name than the select alias.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/7f77835b2a91e131. Report an issue: GitHub.