Skip to content

[SQL] Optimization removing a DISTINCT from the RHS of a LEFT JOIN - #6824

Merged
mihaibudiu merged 1 commit into
feldera:mainfrom
mihaibudiu:antijoin-distinct-rule
Aug 7, 2026
Merged

[SQL] Optimization removing a DISTINCT from the RHS of a LEFT JOIN#6824
mihaibudiu merged 1 commit into
feldera:mainfrom
mihaibudiu:antijoin-distinct-rule

Conversation

@mihaibudiu

@mihaibudiu mihaibudiu commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Checklist

  • Unit tests added/updated

This will rewrite something like

SELECT ...r... LEFT JOIN (SELECT DISTINCT ...)
WHERE r IS NULL AND ...

by removing the DISTINCT when the r column is from the RHS of the join (and is not nullable in the input).
If the column is NULL it must be that it didn't have a match on the LHS, and thus duplicates don't matter.

@ryzhyk

ryzhyk commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

If the column is NULL it must be that it didn't have a match on the LHS, and thus duplicates don't matter.

This doesn't seem right. The column can also be null if there is a match but the value is null in the table.

@mythical-fred mythical-fred left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nice, tight optimization. The correctness argument is easy to check: with a LEFT join, an unmatched left row produces one NULL-padded row regardless of RHS multiplicity, and a matched left row produces rows where the right column is non-NULL (given non-nullability below the aggregate) — so the IS NULL filter deletes them whether the RHS is deduplicated or not. Guards match: LEFT only, Aggregate.Group.SIMPLE + empty agg calls + full-column grouping, and nullability checked on aggregate.getInput().getRowType() rather than the join-padded row type.

Tests are the strong part — six focused unit tests on RelBuilder plans plus SQL-level tests including a Postgres-validated segment query with a mixed IS NOT NULL / IS NULL pair, exercising exactly the branch the rule rewrites. LGTM.

@mihaibudiu
mihaibudiu added this pull request to the merge queue Aug 7, 2026
@gz
gz removed this pull request from the merge queue due to a manual request Aug 7, 2026
@gz
gz added this pull request to the merge queue Aug 7, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 7, 2026
Signed-off-by: Mihai Budiu <mbudiu@feldera.com>
@mihaibudiu
mihaibudiu force-pushed the antijoin-distinct-rule branch from 3933983 to 6ae14ae Compare August 7, 2026 06:45
@mihaibudiu
mihaibudiu enabled auto-merge August 7, 2026 06:45
@mihaibudiu
mihaibudiu added this pull request to the merge queue Aug 7, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 7, 2026
@mihaibudiu
mihaibudiu added this pull request to the merge queue Aug 7, 2026

@mythical-fred mythical-fred left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Rebased over main; content unchanged vs prior approved tip except a single showFinal() debug line removed from testSegment in AntiJoinDistinctTests.java. Approve stands.

@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 7, 2026
@mihaibudiu
mihaibudiu added this pull request to the merge queue Aug 7, 2026
Merged via the queue into feldera:main with commit 553c66e Aug 7, 2026
1 check passed
@mihaibudiu
mihaibudiu deleted the antijoin-distinct-rule branch August 7, 2026 18:37
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.

3 participants