Skip to content

Feature: Implement Extremum Rewrite for ANY Inequalities - #24090

Merged
lnkuiper merged 4 commits into
duckdb:mainfrom
sdk011:issue-23988-all-extremum-rewrite
Jul 28, 2026
Merged

lnkuiper merged 4 commits into
duckdb:mainfrom
sdk011:issue-23988-all-extremum-rewrite

Conversation

@sdk011

@sdk011 sdk011 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

What's Changed

This PR introduces optimization for ALL and ANY inequalities (<, <=, >, >=) by rewriting them into generic Extremum aggregations using a LogicalAggregate and a scalar CASE expression.

This transforms O(N*M) nested loop resolutions into O(N+M) hash join operations, improving performance for these subqueries.

Details

  • Intercepts <, <=, >, >= ANY conditions in both Uncorrelated (PlanUncorrelatedSubquery) and Correlated (PlanCorrelatedSubquery) code paths.
  • Pushes a LogicalAggregate calculating MIN, MAX, COUNT(*), and COUNT(child) onto the subquery.
  • Evaluates the inequality natively via a complex CASE scalar expression that respects SQL's Three-Valued Logic matrix.
  • Accurately supports all edge cases: Multi-column structs, NULL values on the LHS, NULL values inside the subquery, empty global queries, empty correlated groups, and string locale collations.

Testing

  • Adjusted static optimizer tests in statistics_join.test to expect the correctly pushed down ANY_JOIN generated by the rewrite.
  • Added sqllogictests in any_extremum_rewrite.test that covers these three-valued-logic permutation for both correlated and uncorrelated structures.

Closes #23988

@duckdb-draftbot
duckdb-draftbot marked this pull request as draft July 23, 2026 14:46
@sdk011
sdk011 marked this pull request as ready for review July 23, 2026 14:46
This PR introduces a substantial optimization for ALL/ANY inequalities (<, <=, >, >=) by rewriting them into generic Extremum aggregations (MIN, MAX, COUNT(*), COUNT(child)) using a LogicalAggregate and a scalar CASE expression. This fundamentally transforms O(N*M) nested loop resolutions into O(N+M) hash join operations, resulting in massive speedups for large scale datasets.

This works gracefully for both uncorrelated global subqueries and fully correlated subqueries. Robust sqllogictests have been added covering Three-Valued Logic edge cases (Empty sets, LHS NULLs, and RHS NULLs).
@sdk011
sdk011 force-pushed the issue-23988-all-extremum-rewrite branch from 6ff1dbb to 26aa016 Compare July 24, 2026 00:59
@duckdb-draftbot
duckdb-draftbot marked this pull request as draft July 24, 2026 00:59
@sdk011
sdk011 marked this pull request as ready for review July 24, 2026 01:00
@sdk011

sdk011 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

@kryonix , @lnkuiper - can you review this PR ?

@lnkuiper

Copy link
Copy Markdown
Member

Thanks for the PR! I think there's a correctness issue with collations. Could we preserve the comparison collation when computing the extremum? The rewrite currently binds MIN/MAX over the raw RHS column, and only applies the requested collation to the final comparison. Since the extremum can differ under that collation, this changes the result of the quantified predicate.

For example, on this PR:

SELECT 'b' COLLATE NOCASE >
       ANY (SELECT x FROM (VALUES ('Z'), ('a')) t(x));

This should return true, since b > a under NOCASE, but the rewrite returns false because the binary MIN is Z. Could we propagate the comparison collation to the MIN/MAX aggregate argument (or otherwise compute the extremum using the same ordering)?

Repro:

# name: test/temp.test
# description: ANY extremum rewrite must preserve collations
# group: [optimizer]

query I
SELECT 'b' COLLATE NOCASE > ANY(SELECT x FROM (VALUES ('Z'), ('a')) t(x));
----
true

Can you also add a TODO/FIXME that we should get this to work for multi-column in the future? This works for single column only right now (which is fine!).

@duckdb-draftbot
duckdb-draftbot marked this pull request as draft July 28, 2026 04:37
@sdk011
sdk011 marked this pull request as ready for review July 28, 2026 04:43
@lnkuiper

Copy link
Copy Markdown
Member

Thanks for the changes! Ready to merge from my side once the merge conflict is resolved

@duckdb-draftbot
duckdb-draftbot marked this pull request as draft July 28, 2026 13:18
@sdk011
sdk011 marked this pull request as ready for review July 28, 2026 13:18
@duckdb-draftbot
duckdb-draftbot marked this pull request as draft July 28, 2026 13:38
@sdk011
sdk011 marked this pull request as ready for review July 28, 2026 13:39
@lnkuiper
lnkuiper enabled auto-merge July 28, 2026 13:51
@lnkuiper
lnkuiper added this pull request to the merge queue Jul 28, 2026
Merged via the queue into duckdb:main with commit f919089 Jul 28, 2026
109 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ALL misses extremum rewrite

2 participants