You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Wrong results: LATERAL with SELECT DISTINCT and a non-equality correlated filter returns duplicate rows #25808
A LATERAL subquery with SELECT DISTINCT and a correlated filter that is not an equality (for example >) returns duplicate rows. The correlated filter is pulled above the DISTINCT, and the column that the filter reads is added to the DISTINCT keys. Rows that differ only in that column are then not merged.
To Reproduce
CREATETABLEpo(k INT) ASVALUES (0), (5);
CREATETABLEpb(x INT, y INT) ASVALUES (1, 1), (1, 2), (2, 3);
SELECTpo.k, s.xFROM po, LATERAL (SELECT DISTINCTpb.xFROM pb WHEREpb.y>po.k) AS s
ORDER BYpo.k, s.x;
For po.k = 0, all three rows of pb match, and the distinct values of x are 1 and 2.
DataFusion
DuckDB 1.5.2
PostgreSQL 17.11
(0, 1), (0, 1), (0, 2)
(0, 1), (0, 2)
(0, 1), (0, 2)
The same query with GROUP BY instead of DISTINCT does not give wrong results. DataFusion does not decorrelate it and fails with a not-implemented error:
SELECTpo.k, s.x, s.nFROM po, LATERAL (SELECTpb.x, count(*) AS n FROM pb WHEREpb.y>po.kGROUP BYpb.x) AS s;
-- This feature is not implemented: Physical plan does not support logical expression OuterReferenceColumn(...)
With an equality filter (pb.y = po.k) the DISTINCT form gives the correct result.
Expected behavior
The results of DuckDB and PostgreSQL above: each distinct x one time for each po row.
Additional context
The plan shows the cause. pb.y is now a group-by key of the DISTINCT aggregate, and pb.y > po.k is the join filter:
In PullUpCorrelatedExpr::f_up in datafusion/optimizer/src/decorrelate.rs, the Aggregate arm does the can_pull_over_aggregation check only when the aggregate is not a DISTINCT. That check allows only equality filters to move above an aggregate. For EXISTS and IN, adding a column to the DISTINCT keys does not change the result, because duplicate rows do not change whether a match exists. For LATERAL, every row is output, so the duplicate rows are visible.
A fix can do the can_pull_over_aggregation check for a DISTINCT aggregate as well, except for EXISTS and IN subqueries. The GROUP BY form already gets this check.
When fixing this bug, I think we should make the query error rather than trying to make it work / give correct results. To make it work and have confidence it will be correct, I think we need a more general approach than patches. See here for details
Activity
fix: pull correlated filters through Window and Unnest when safe
fix: prevent pulling non-equality filters through DISTINCT in LATERAL…
fix: pull a correlated filter only through plan nodes known to be safe (
fix: pull a correlated filter only through plan nodes known to be safe (
alamb commentedon Oct 28, 2026
When fixing this bug, I think we should make the query error rather than trying to make it work / give correct results. To make it work and have confidence it will be correct, I think we need a more general approach than patches. See here for details