adriangb opened a new issue, #25808:
URL: https://github.com/apache/datafusion/issues/25808

   ### Describe the bug
   
   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
   
   ```sql
   CREATE TABLE po(k INT) AS VALUES (0), (5);
   CREATE TABLE pb(x INT, y INT) AS VALUES (1, 1), (1, 2), (2, 3);
   
   SELECT po.k, s.x
   FROM po, LATERAL (SELECT DISTINCT pb.x FROM pb WHERE pb.y > po.k) AS s
   ORDER BY po.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:
   
   ```sql
   SELECT po.k, s.x, s.n
   FROM po, LATERAL (SELECT pb.x, count(*) AS n FROM pb WHERE pb.y > po.k GROUP 
BY pb.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:
   
   ```
   Projection: po.k, s.x
     Inner Join:  Filter: s.y > po.k
       TableScan: po projection=[k]
       SubqueryAlias: s
         Aggregate: groupBy=[[pb.x, pb.y]], aggr=[[]]
           TableScan: pb projection=[x, y]
   ```
   
   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.
   
   Found on `main` at 6a792c6713.
   
   This is the same class of bug as these: `PullUpCorrelatedExpr` pulls a 
correlated filter through a plan node where that changes the result.
   
   - https://github.com/apache/datafusion/issues/25507 (outer join)
   - https://github.com/apache/datafusion/issues/25792 (window function)
   - https://github.com/apache/datafusion/issues/25283 (`Limit` with an 
`OFFSET`)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to