Aggregates get their real power when applied per group. Today you add GROUP BY, partitioning rows by a column and emitting one aggregated row per distinct value.
Execute a SELECT with GROUP BY so each distinct value of the grouping column yields one aggregated row.
GROUP BY turns one whole-table aggregate into one aggregate per group.
Execution partitions the filtered rows by the grouping column’s value - all the
NYC rows together, all the LA rows together - then, for each group, emits a
row containing the group key and every aggregate computed over just that group’s
rows. SELECT city, COUNT(*) ... GROUP BY city becomes one row per city with its
count.
Preserve first-seen order of the group keys so results are deterministic
(NYC before LA because alice came first). The select list in a grouped query
is now a mix of the grouping column and aggregate calls, which is exactly what
your parser already produces. This is the most powerful query shape in the engine;
next you let a query filter on the aggregated result itself.
// parse: optional GROUP BY <column> after WHERE// execute: partition filtered rows by the group column's value// (preserve first-seen order); for each group, emit the group key// column plus each aggregate computed over that group's rows