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

   
   ### Describe the bug
   
   `ORDER BY <col> LIMIT k` above an aggregate can be pushed into the aggregate 
(`lim=[k]`), so the aggregate keeps only the top `k` groups. To find the 
aggregate column, the rule follows the sort column **by name** through 
projections. If a projection computes a new value and gives it the same name as 
the aggregate output, for example `-"max(t.v)" AS "max(t.v)"`, the rule treats 
it as the aggregate column and picks the top groups by the original value 
instead of the computed one.
   
   ### To Reproduce
   
   In `datafusion-cli`:
   
   ```sql
   CREATE TABLE t AS SELECT column1 AS g, column2 AS v
   FROM (VALUES ('a', 2), ('b', 10), ('c', 9), ('d', 3), ('e', 7));
   
   SELECT g, -"max(t.v)" AS "max(t.v)"
   FROM (SELECT g, max(v) FROM t GROUP BY g)
   ORDER BY 2 DESC LIMIT 2;
   ```
   
   ```text
   +---+----------+
   | g | max(t.v) |
   +---+----------+
   | c | -9       |
   | b | -10      |
   +---+----------+
   ```
   
   ```text
   SortPreservingMergeExec: [max(t.v)@1 DESC], fetch=2
     SortExec: TopK(fetch=2), expr=[max(t.v)@1 DESC], 
preserve_partitioning=[true]
       ProjectionExec: expr=[g@0 as g, (- max(t.v)@1) as max(t.v)]
         AggregateExec: mode=FinalPartitioned, gby=[g@0 as g], aggr=[max(t.v)], 
lim=[2]
           RepartitionExec: partitioning=Hash([g@0], 12), input_partitions=1
             AggregateExec: mode=Partial, gby=[g@0 as g], aggr=[max(t.v)], 
lim=[2]
   ```
   
   ### Expected behavior
   
   The two largest values of `-max(v)` are `-2` (`a`) and `-3` (`d`). That is 
what `SET datafusion.optimizer.enable_topk_aggregation = false;` returns:
   
   ```text
   +---+----------+
   | g | max(t.v) |
   +---+----------+
   | a | -2       |
   | d | -3       |
   +---+----------+
   ```
   
   ### Additional context
   
   The name tracking is in 
`datafusion/physical-optimizer/src/topk_aggregation.rs` (around lines 83-92). 
For each projection expression, the rule only looks at plain `Column` 
expressions (`continue` on anything else) to follow renames. It never notices 
that the name it is tracking now belongs to a computed expression, so it keeps 
looking for that name below and finds the aggregate's `max(t.v)`. A fix is to 
stop (no TopK aggregation) when the tracked name is produced by any expression 
other than a plain column.
   
   The same walk continues through any other operator whose 
`cardinality_effect()` is `Equal` or `GreaterEqual` and keeps the name 
unchanged (around lines 95-96). That is only correct if the operator also 
passes the column through unchanged.
   
   The group key has to be a type TopK aggregation supports. With a `VARCHAR` 
column (which becomes `Utf8View`) the rule does not fire, and the result is 
correct.
   
   ### Willingness to contribute
   
   I cannot contribute a fix for this bug at this time
   


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