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: correlated EXISTS/IN subqueries over a groupless aggregate get the wrong outer rows #24960
A correlated EXISTS or IN subquery containing a groupless aggregate (e.g. count(*), with no GROUP BY) returns incorrect results when the outer row has 0 matches on the subquery.
A groupless aggregate always produces exactly one output row, even over zero input rows. The current decorrelation instead drops the outer row entirely, as if the subquery had produced no rows at all.
To Reproduce
CREATETABLEt1(t1_int int); INSERT INTO t1 VALUES (1),(2),(3);
CREATETABLEt2(t2_int int); INSERT INTO t2 VALUES (2);
SELECTt1.t1_intFROM t1 WHERE EXISTS (
SELECTcount(*) FROM t2 WHEREt1.t1_int=t2.t2_int
) ORDER BY1;
Expected behavior
The query above should return all three rows: 1, 2, 3.
For t1_int=1 and t1_int=3, no row in t2 matches, so the inner count(*) evaluates to 0 rather than producing no row at all. A 0 is still a row, so EXISTS should be true for those two outer rows too.
Currently, DataFusion returns a single row, 2, silently dropping the two rows whose count(*) evaluated to 0.
The NOT EXISTS variant of the same query surfaces the same underlying bug. It should return no rows (since EXISTS is true for every row) but instead returns 1, 3.
changed the title [-]Correlated `EXISTS`/`IN` subqueries with groupless aggregates hit the count bug[/-][+]Wrong results: correlated `EXISTS`/`IN` subqueries over a groupless aggregate get the wrong outer rows[/+]on Sep 21, 2026
On main (ebf4858) the IN/NOT IN forms still return wrong rows rather than a "not implemented" error:
CREATETABLEt1(a INT) ASVALUES (1),(2);
CREATETABLEt2(a INT, b INT) ASVALUES (1,10),(1,NULL);
SELECT a FROM t1 WHERE0IN (SELECTcount(*) FROM t2 WHEREt2.a=t1.a); -- returns no rows, expected 2SELECT a FROM t1 WHERE0 NOT IN (SELECTcount(*) FROM t2 WHEREt2.a=t1.a); -- returns 1, 2, expected 1SELECT a, 0IN (SELECTcount(*) FROM t2 WHEREt2.a=t1.a) FROM t1; -- a = 2 gives false, expected true
The IN path never turns on the count bug handling (decorrelate_predicate_subquery.rs, build_join runs the pull up with it on only for EXISTS).
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
[-]Correlated `EXISTS`/`IN` subqueries with groupless aggregates hit the count bug[/-][+]Wrong results: correlated `EXISTS`/`IN` subqueries over a groupless aggregate get the wrong outer rows[/+]fix: correlated exists/not exists subqueries hit the count bug for gr…
jayzhan211 commentedon Oct 23, 2026
On main (ebf4858) the
IN/NOT INforms still return wrong rows rather than a "not implemented" error:The IN path never turns on the count bug handling (
decorrelate_predicate_subquery.rs,build_joinruns the pull up with it on only forEXISTS).fix: reject correlated IN/NOT IN over a groupless aggregate (apache#2…
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
raghavyadav01 commentedon Oct 29, 2026
Checked on current main (14aa185):
EXISTS/NOT EXISTSrepro in the description is correct now (1, 2, 3and no rows, same as DuckDB 1.5.6)INqueries from Wrong results: correlatedEXISTS/INsubqueries over a groupless aggregate get the wrong outer rows #24960 (comment) now fail withPhysical plan does not support logical expression InSubqueryinstead of returning wrong rowsOne shape still returns wrong rows, a
HAVINGthat reads both the count and an outer column:It looks related to #26695, but that one is about a
HAVINGon outer columns only, so I'd keep this open for now.