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

   ### Describe the bug
   
   A subquery (`EXISTS`, `IN` or a scalar subquery) inside an aggregate, that 
is in a `GROUP BY` key, an aggregate argument or an aggregate `FILTER`, fails 
at physical planning with `This feature is not implemented: Physical plan does 
not support logical expression ...`. The same subquery in the `SELECT` list or 
in `WHERE` works.
   
   ### To Reproduce
   
   ```sql
   CREATE TABLE t1 (a INT, b VARCHAR, x INT);
   INSERT INTO t1 VALUES (1, 'p', 10), (2, 'p', 20), (3, 'q', 30), (NULL, 'q', 
40), (2, 'q', 50);
   CREATE TABLE t2 (a INT, y INT);
   INSERT INTO t2 VALUES (2, 7), (2, 9), (3, 5), (NULL, 1);
   
   -- Query 1
   SELECT count(*) FILTER (WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.a = t1.a)) 
AS n FROM t1;
   -- Query 2
   SELECT CASE WHEN EXISTS (SELECT 1 FROM t2 WHERE t2.a = t1.a) THEN 'yes' ELSE 
'no' END AS has_t2, count(*) AS n
   FROM t1 GROUP BY 1 ORDER BY 1;
   -- Query 3
   SELECT sum(CASE WHEN t1.a IN (SELECT a FROM t2) THEN t1.x ELSE 0 END) AS s 
FROM t1;
   -- Query 4
   SELECT t1.b, sum((SELECT max(t2.y) FROM t2 WHERE t2.a = t1.a)) AS s FROM t1 
GROUP BY t1.b ORDER BY t1.b;
   -- Query 5
   SELECT count(*) FILTER (WHERE t1.a NOT IN (SELECT a FROM t2)) AS n FROM t1;
   ```
   
   ### Expected behavior
   
   | Query | Subquery is in | DataFusion returns | Expected |
   |---|---|---|---|
   | 1 | aggregate `FILTER` | `Physical plan does not support logical 
expression Exists(...)` | `3` |
   | 2 | `GROUP BY` key | `Physical plan does not support logical expression 
Exists(...)` | `no, 2` and `yes, 3` |
   | 3 | aggregate argument | `Physical plan does not support logical 
expression InSubquery(...)` | `100` |
   | 4 | aggregate argument | `Physical plan does not support logical 
expression ScalarSubquery(<subquery>)` | `p, 9` and `q, 14` |
   | 5 | aggregate `FILTER` | `Physical plan does not support logical 
expression InSubquery(...)` | `0` (`t2.a` has a `NULL`, so `NOT IN` is never 
true) |
   
   DuckDB returns the expected results.
   
   ### Additional context
   
   - The cause: `DecorrelatePredicateSubquery` and `ScalarSubqueryToJoin` 
rewrite subqueries only in `Filter` and `Projection` nodes 
(`decorrelate_predicate_subquery.rs` matches `LogicalPlan::Projection` and 
`LogicalPlan::Filter`, `scalar_subquery_to_join.rs` the same two). The 
expressions of an `Aggregate` are never visited, so their subqueries reach the 
physical planner unchanged.
   - This shows up in the dbolympics benchmark (#26661): 13 of its 409 queries 
put a subquery in an aggregate (q057, q084, q085, q091, q135, q136, q156, q178, 
q182, q312, q315, q370, q409).
   - A fix direction that removes the cause: compute each aggregate expression 
that contains a subquery in a `Projection` below the `Aggregate`, keeping the 
output names with aliases. These expressions are evaluated once per input row 
anyway, and the existing rules then decorrelate the subquery in that 
`Projection`. I tried this in a prototype (one new optimizer rule placed before 
`DecorrelatePredicateSubquery`):
     - Queries 1-5 return the expected results, as do harder cases (several 
subqueries in one aggregate, `count(DISTINCT ...)`, an aggregate `ORDER BY`, an 
aggregate inside a correlated subquery, `NOT EXISTS`, empty input).
     - 10 of the 13 dbolympics queries plan. The other 3 then fail on a scalar 
subquery with `ORDER BY ... LIMIT 1`, which is a separate gap.
     - No other dbolympics query starts or stops failing, and all sqllogictest 
files and optimizer tests pass (the only expected-output change is the new 
rule's line in `EXPLAIN VERBOSE`).
     - Like `ScalarSubqueryToJoin`, it leaves an uncorrelated scalar subquery 
where it is, since `ScalarSubqueryExec` already runs it.
   - Not covered by that approach: a subquery in a `ROLLUP` / `GROUPING SETS` 
key. It fails differently on main today (`Schema error: No field named t1.a`).
   - Related: #5492 (general decorrelation framework).
   
   ### Willingness to contribute
   
   I'm not planning to fix this myself, so anyone is welcome to pick it up. 
Feel free to ping me with questions about the cause or when you'd like a review.
   


-- 
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