Skip to content

docs: Clarify that subquery ORDER BY is ignored by order-sensitive aggregates#37537

Merged
antiguru merged 2 commits into
MaterializeInc:mainfrom
antiguru:bridge-cse_01QV1HdXzT7YEJRKQazUrBQe
Jul 14, 2026
Merged

docs: Clarify that subquery ORDER BY is ignored by order-sensitive aggregates#37537
antiguru merged 2 commits into
MaterializeInc:mainfrom
antiguru:bridge-cse_01QV1HdXzT7YEJRKQazUrBQe

Conversation

@antiguru

@antiguru antiguru commented Jul 9, 2026

Copy link
Copy Markdown
Member

PostgreSQL honors an ORDER BY in a subquery that feeds an order-sensitive aggregate (array_agg, string_agg, ...) as an executor artifact, so array_agg(i) FROM (SELECT ... ORDER BY ...) comes out sorted.
This is not guaranteed by the SQL standard, and Materialize does not reproduce it: a nested query is an unordered relation whose ORDER BY is dropped unless combined with a row-limiting clause.
Aggregation order must be requested with the in-aggregate agg(value ORDER BY ...) form.

This documents the divergence at the drop site in plan_nested_query, and replaces the shared boilerplate across array_agg, string_agg, list_agg, jsonb_agg, and jsonb_object_agg.
It previously claimed both "as if sorted in ascending order" and "not guaranteed any order"; it now states the aggregation order is unspecified without an in-aggregate ORDER BY.
Reference examples that documented the implementation-defined ascending order as if guaranteed are removed.

No behavior change.

CLU-160

…gregates

PostgreSQL honors an ORDER BY in a subquery that feeds an order-sensitive
aggregate (array_agg, string_agg, ...) as an executor artifact, so a query
like `array_agg(i) FROM (SELECT ... ORDER BY ...)` comes out sorted. This
behavior is not guaranteed by the SQL standard, and Materialize does not
reproduce it: a nested query is an unordered relation, and its ORDER BY is
dropped unless combined with a row-limiting clause. Aggregation order must be
requested with the in-aggregate `agg(value ORDER BY ...)` form.

Document the divergence at the drop site in plan_nested_query, and replace the
shared boilerplate across array_agg, string_agg, list_agg, jsonb_agg, and
jsonb_object_agg. It previously claimed both "as if sorted in ascending order"
and "not guaranteed any order"; it now states that the aggregation order is
unspecified without an in-aggregate ORDER BY. Also remove reference examples
that documented the implementation-defined ascending order as if it were
guaranteed.

CLU-160

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@antiguru antiguru force-pushed the bridge-cse_01QV1HdXzT7YEJRKQazUrBQe branch from 225a1ef to cac3d5e Compare July 9, 2026 19:51
@antiguru antiguru marked this pull request as ready for review July 10, 2026 14:52
@antiguru antiguru requested review from a team as code owners July 10, 2026 14:52
@antiguru antiguru requested a review from kay-kim July 10, 2026 14:52

This function always executes on the data from `value` as if it were sorted in ascending order before the function call. Any specified ordering is
ignored. If you need to perform aggregation in a specific order, you must specify `ORDER BY` within the aggregate function call itself. Otherwise incoming rows are not guaranteed any order.
Any `ORDER BY` applied to the input rows, for example in a feeding subquery, is

@kay-kim kay-kim Jul 10, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Is the first sentence more

Any ORDER BY applied before the aggregate function is evaluated (such as in an input subquery) is ignored.

(or does this broaden it too much?)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went with your phrasing, thanks. Broadening it is correct: it's not just subqueries, any ORDER BY on an unordered input (a CTE, a view, etc.) gets dropped the same way. Pushed in 2a64898.

This function always executes on the data from `value` as if it were sorted in ascending order before the function call. Any specified ordering is
ignored. If you need to perform aggregation in a specific order, you must specify `ORDER BY` within the aggregate function call itself. Otherwise incoming rows are not guaranteed any order.
Any `ORDER BY` applied to the input rows, for example in a feeding subquery, is
ignored. The order in which values are aggregated is otherwise unspecified. To

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just combine the two last sentences to (?)

Unless ORDER BY is included in the aggregate function call itself, the order in which the values are aggregated is unspecified.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh ... we can also single source this in a
doc/user/content/headless/blah.md
and just include it via `{{% include-headless "/headless/blah" %}}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, done both. Merged the two sentences per your suggestion, and pulled the whole paragraph into doc/user/content/headless/aggregate-input-order-ignored.md, included from all five function docs instead of duplicating it five times. Pushed in 2a64898.

Address review feedback on MaterializeInc#37537: five function docs carried an
identical paragraph explaining that ORDER BY on the aggregate's input
is ignored. Fold it into a headless partial and tighten the wording
per review suggestion.
@antiguru antiguru merged commit efc8864 into MaterializeInc:main Jul 14, 2026
129 checks passed
@antiguru antiguru deleted the bridge-cse_01QV1HdXzT7YEJRKQazUrBQe branch July 14, 2026 10:58
@antiguru

Copy link
Copy Markdown
Member Author

Thanks for the review!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants