Repository navigation
Closed
Labels
bugSomething isn't workingSomething isn't workinghelp wantedExtra attention is neededExtra attention is needed
Description
Describe the bug
A clear and concise description of what the bug is.
To Reproduce
using datafusion-cli load some data:
❯ create or replace table t as select column1 as value, column2 as time from (select * from (values
(1, timestamp '2022-01-01 00:00:00'),
(2, timestamp '2022-01-01 01:00:00'),
(3, timestamp '2022-01-02 00:00:00')
) as sq) as sq
;
0 rows in set. Query took 0.001 seconds.
❯ select * from t;
+-------+---------------------+
| value | time |
+-------+---------------------+
| 1 | 2022-01-01T00:00:00 |
| 2 | 2022-01-01T01:00:00 |
| 3 | 2022-01-02T00:00:00 |
+-------+---------------------+
3 rows in set. Query took 0.001 seconds.
❯ ;GROUP BY "time" works:
❯ select
sum(value) AS "value",
date_trunc('hour',time) AS "time"
FROM t
GROUP BY time;
+-------+---------------------+
| value | time |
+-------+---------------------+
| 3 | 2022-01-02T00:00:00 |
| 2 | 2022-01-01T01:00:00 |
| 1 | 2022-01-01T00:00:00 |
+-------+---------------------+
3 rows in set. Query took 0.002 seconds.However, GROUP BY "time" ORDER BY "time" does not work:
❯ select
sum(value) AS "value",
date_trunc('month',time) AS "time"
FROM t
GROUP BY time
ORDER BY time;
SchemaError(AmbiguousReference { qualifier: Some("t"), name: "time" })Expected behavior
I expect the query to run and produce ordered results like postgres:
postgres=# select
sum(value) AS "value",
date_trunc('month',time) AS "time"
FROM t
GROUP BY time
ORDER BY time;
value | time
-------+---------------------
3 | 2022-01-01 00:00:00
2 | 2022-01-01 00:00:00
1 | 2022-01-01 00:00:00
(3 rows)Additional context
Note I was confused about why this query wasn't actually aggregating on the truncated date (as in why are there 3 output rows rather than 1 output row). The reason is that the GROUP BY time is (correctly) evaluated before the date_trunc function evaluated in the select list.
To group by the truncated date, you need to group by date_trunc('month',time) AS "time" , which you can do using 2
select
sum(value) AS "value",
date_trunc('month',time) AS "time"
FROM t
GROUP BY 2
ORDER BY 2;
+-------+---------------------+
| value | time |
+-------+---------------------+
| 6 | 2022-01-01T00:00:00 |
+-------+---------------------+
1 row in set. Query took 0.005 seconds.Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workinghelp wantedExtra attention is neededExtra attention is needed
Activity
[-]can not ORDER BY a an aliased group column[/-][+]Can not ORDER BY an aliased group column[/+]crepererum commentedon Jan 10, 2023
Note that
ORDER BYuses the columns generated byGROUP BY, NOT the original columns. This can be checked w/ postgres:Also note that columns that are NOT part of the
GROUP BYoutput cannot be used inORDER BY:Looking at the current
LogicalPlanBuilder::sortcode it seems that the "missing column"-handling or therewrite_sort_cols_by_aggsbit in there are somewhat broken.alamb commentedon Jan 10, 2023
cc @jackwener who may have some ideas
FWIW the logical order of operations is like this (from https://learnsql.com/blog/sql-order-of-operation)
So as you are describing yes the columns which are available to ORDER are the output of the GROUP BY -- so that means either
GROUP BYcolumns or aggregates (or some expression of them)For example, this is valid:
jackwener commentedon Jan 11, 2023
I debug this bug.
Before apply
Sort, the plan is:Error in
rewrite_sort_cols_by_aggsjackwener commentedon Jan 11, 2023
I have found this BUG.
It's because
rewrite_sort_col_by_aggs. When meetLogicalProject(), it will go through it, and continue findAggregate.So, it will bind
sort time->sort t.time. When meetsum(value) AS "value"in projection, it cause AmbiguousReference.crepererum commentedon Jan 11, 2023
I came up with a similar conclusion, but honestly wasn't able to puzzle the pieces together and figure out which part exactly should be changed. I leave the fix to @jackwener then 😊
jackwener commentedon Jan 12, 2023
I will try to fix it.🚀
jackwener commentedon Jan 21, 2023
So sorry for late do it. Recent I am busy working🥲.
I've been investigating this for a while. But I find It isn't easy thing.
In standard sql,
order byis afterproject. BUT, in fact, reality is not so.order byis fromproject.but sometime
order byis from child ofproject. For example:we can find
order byis before project.So, when exist
aggregation. like abovetwo condition: orderby-project-agg / project-orderby-agg.
In this sql,
order-by: time,timeexist inagg, so datafusion useproject-orderby-agg, but in fact,timeis fromproject.We should prefer to use
orderby-project-aggand if fail then useproject-orderby-aggalamb commentedon Jan 23, 2023
Hi @jackwener -- you are right this is tricky. I think the correct semantics are to resolve the ORDER BY in terms of the output schema of the stage (not the output of the select list)
As I recall the way postgres handled this case was to add
price+1to the select list but mark it "hidden" so it was removed from the final select listMaybe we can also special case using the postgres model of "resolve using select list" and if that is not possible, try and "pull" up relevant columns through the Projection. For example, if the input Plan to
order_byhttps://github.com/apache/arrow-datafusion/blob/master/datafusion/sql/src/query.rs#L144 wasAnd the sort was by
column2:Today the code will try to put the sort above the projection:
Perhaps we could put the Sort below the Projection like
🤔
I can take a shot at doing this if you wanted. A few of our users have hit this so I am incentivized to try and help this
Here are some other examples from postgres
But for trickier stuff postgres requires the expressions to appear directly in the select list
jackwener commentedon Jan 25, 2023
Thanks you❤️
alamb commentedon Jan 25, 2023
👍 @jackwener I plan on working on this later today
alamb commentedon Jan 26, 2023
I am making progress on this ticket -- I will provide a better update tomorrow.
alamb commentedon Jan 27, 2023
I believe I have a solution here #5067 (but I broke out some mechanical changes in #5092 and #5088 which need to be reviewed first)