Add GROUP BY and aggregates - #6
Merged
Merged
Conversation
Supports `select status, count(*) as n, sum(total) from t group by status`
with count(*), count(field), sum, min, max and avg. Aggregates can take an
alias. An aggregate without GROUP BY covers the whole table. ORDER BY can
name a group field, an aggregate or an alias, and LIMIT limits the groups.
The grammar gains GROUP BY, aggregate calls in the select list and ORDER
BY, and AS aliases. The translator checks grouping rules (selected fields
must be grouped, known aggregate names, * only for count) and names the
output columns. The planner plans the underlying scan as before, reading
only the fields that are grouped or aggregated, so WHERE keeps index and
primary-key pushdown. An {:aggregate, ...} operator (Efsql.Aggregate) then
groups the rows, followed by sort, limit and project.
SQL semantics: count(*) counts rows and the other aggregates skip NULLs.
NULLs form one group. Values that compare equal group together even when
their terms differ, like Decimal 1.0 and 1.00. An aggregate over no rows
still returns one row. sum and avg are Decimal when any input is.
HAVING stays unsupported. Completion, the help page and the README cover
the new syntax, and the random query generator produces aggregates and
GROUP BY for the property tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PFBZUrerge6bbWVCHpS5Ko
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
efsql can now count and summarize, not just list rows:
What's supported
count(*),count(field),sum,min,maxandavg, each optionally named withAS. An aggregate withoutGROUP BYgives one row for the whole table.ORDER BYa group field, an aggregate or its alias. An aggregate you only sort by doesn't have to be selected; it's computed and dropped.LIMITlimits the groups.count(*)counts rows, everything else skips NULLs, and NULLs form one group. An aggregate over no rows is still one row (count(*)is 0).sum/avghandle numbers andDecimals, andmin/maxwork on strings and datetimes too.Decimal1.0 and 1.00, or timestamps stored at different precisions.HAVINGis still refused by name.How it runs
The planner plans the underlying scan the same way as any other query, reading only the fields that are grouped or aggregated. So
WHEREkeeps its index and primary key pushdown. After that, a new{:aggregate, group_by, aggregates}operator (Efsql.Aggregate) groups the pulled rows, then sort, limit and project run as usual.Efsql.Aggregateis pure, so its tests don't need FoundationDB.In the grammar this adds
GROUP BY, aggregate calls andAS, with no conflicts. The error messages for the new syntax come straight from the grammar. For example, afterselect athe parser now saysexpected FROM, '(' or ','.Also
group/by, the help page has a Grouping section, and the README documents all of it.GROUP BY, so the round-trip and never-crash property tests cover them.Tests
Efsql.Aggregate, for translating and validating grouped queries, and for parsing and completion.test/group_by_test.exsruns grouped queries against FoundationDB. It also checks the plan:WHEREstill goes to the index, only the needed fields are read, and the limit isn't pushed to the adapter. This CI run is the first time those tests run, since I didn't have FoundationDB locally. Everything else (199 tests) passes locally.One thing that hasn't changed: result columns still show up alphabetically rather than in select-list order, the same as for plain queries.
🤖 Generated with Claude Code
https://claude.ai/code/session_01PFBZUrerge6bbWVCHpS5Ko
Generated by Claude Code