mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-21 01:00:48 +00:00
Fix projections with GROUP/ORDER BY in query and optimize_aggregation_in_order
With projections, GROUP BY/ORDER BY in query, optimize_aggregation_in_order, GROUP BY's InputOrderInfo was used incorrectly for ORDER BY. Signed-off-by: Azat Khuzhin <a.khuzhin@semrush.com>
This commit is contained in:
parent
ef1773f444
commit
e32b695775
@ -1168,6 +1168,12 @@ void InterpreterSelectQuery::executeImpl(QueryPlan & query_plan, std::optional<P
|
||||
LOG_TRACE(log, "{} -> {}", QueryProcessingStage::toString(from_stage), QueryProcessingStage::toString(options.to_stage));
|
||||
}
|
||||
|
||||
if (query_info.projection && query_info.projection->input_order_info && query_info.input_order_info)
|
||||
throw Exception("InputOrderInfo is set for projection and for query", ErrorCodes::LOGICAL_ERROR);
|
||||
InputOrderInfoPtr input_order_info_for_order;
|
||||
if (!expressions.need_aggregate)
|
||||
input_order_info_for_order = query_info.projection ? query_info.projection->input_order_info : query_info.input_order_info;
|
||||
|
||||
if (options.to_stage > QueryProcessingStage::FetchColumns)
|
||||
{
|
||||
auto preliminary_sort = [&]()
|
||||
@ -1183,10 +1189,7 @@ void InterpreterSelectQuery::executeImpl(QueryPlan & query_plan, std::optional<P
|
||||
&& !expressions.has_window)
|
||||
{
|
||||
if (expressions.has_order_by)
|
||||
executeOrder(
|
||||
query_plan,
|
||||
query_info.input_order_info ? query_info.input_order_info
|
||||
: (query_info.projection ? query_info.projection->input_order_info : nullptr));
|
||||
executeOrder(query_plan, input_order_info_for_order);
|
||||
|
||||
if (expressions.has_order_by && query.limitLength())
|
||||
executeDistinct(query_plan, false, expressions.selected_columns, true);
|
||||
@ -1311,16 +1314,9 @@ void InterpreterSelectQuery::executeImpl(QueryPlan & query_plan, std::optional<P
|
||||
executeWhere(query_plan, expressions.before_where, expressions.remove_where_filter);
|
||||
|
||||
if (expressions.need_aggregate)
|
||||
{
|
||||
executeAggregation(
|
||||
query_plan, expressions.before_aggregation, aggregate_overflow_row, aggregate_final, query_info.input_order_info);
|
||||
|
||||
/// We need to reset input order info, so that executeOrder can't use it
|
||||
query_info.input_order_info.reset();
|
||||
if (query_info.projection)
|
||||
query_info.projection->input_order_info.reset();
|
||||
}
|
||||
|
||||
// Now we must execute:
|
||||
// 1) expressions before window functions,
|
||||
// 2) window functions,
|
||||
@ -1455,10 +1451,7 @@ void InterpreterSelectQuery::executeImpl(QueryPlan & query_plan, std::optional<P
|
||||
&& !(query.group_by_with_totals && !aggregate_final))
|
||||
executeMergeSorted(query_plan, "for ORDER BY, without aggregation");
|
||||
else /// Otherwise, just sort.
|
||||
executeOrder(
|
||||
query_plan,
|
||||
query_info.input_order_info ? query_info.input_order_info
|
||||
: (query_info.projection ? query_info.projection->input_order_info : nullptr));
|
||||
executeOrder(query_plan, input_order_info_for_order);
|
||||
}
|
||||
|
||||
/** Optimization - if there are several sources and there is LIMIT, then first apply the preliminary LIMIT,
|
||||
@ -2747,12 +2740,6 @@ void InterpreterSelectQuery::executeExtremes(QueryPlan & query_plan)
|
||||
|
||||
void InterpreterSelectQuery::executeSubqueriesInSetsAndJoins(QueryPlan & query_plan, SubqueriesForSets & subqueries_for_sets)
|
||||
{
|
||||
// const auto & input_order_info = query_info.input_order_info
|
||||
// ? query_info.input_order_info
|
||||
// : (query_info.projection ? query_info.projection->input_order_info : nullptr);
|
||||
// if (input_order_info)
|
||||
// executeMergeSorted(query_plan, input_order_info->order_key_prefix_descr, 0, "before creating sets for subqueries and joins");
|
||||
|
||||
const Settings & settings = context->getSettingsRef();
|
||||
|
||||
SizeLimits limits(settings.max_rows_to_transfer, settings.max_bytes_to_transfer, settings.transfer_overflow_mode);
|
||||
|
@ -0,0 +1,13 @@
|
||||
-- { echoOn }
|
||||
select x + y, sum(x - y) as s from test_agg_proj_02302 group by x + y order by s desc limit 5 settings allow_experimental_projection_optimization=1, optimize_aggregation_in_order=0, optimize_read_in_order=0;
|
||||
15 480
|
||||
14 450
|
||||
13 420
|
||||
12 390
|
||||
11 360
|
||||
select x + y, sum(x - y) as s from test_agg_proj_02302 group by x + y order by s desc limit 5 settings allow_experimental_projection_optimization=1, optimize_aggregation_in_order=1, optimize_read_in_order=1;
|
||||
15 480
|
||||
14 450
|
||||
13 420
|
||||
12 390
|
||||
11 360
|
@ -0,0 +1,13 @@
|
||||
-- Tags: no-s3-storage
|
||||
|
||||
drop table if exists test_agg_proj_02302;
|
||||
|
||||
create table test_agg_proj_02302 (x Int32, y Int32, PROJECTION x_plus_y (select sum(x - y), argMax(x, y) group by x + y)) ENGINE = MergeTree order by tuple() settings index_granularity = 1;
|
||||
insert into test_agg_proj_02302 select intDiv(number, 2), -intDiv(number,3) - 1 from numbers(100);
|
||||
|
||||
-- { echoOn }
|
||||
select x + y, sum(x - y) as s from test_agg_proj_02302 group by x + y order by s desc limit 5 settings allow_experimental_projection_optimization=1, optimize_aggregation_in_order=0, optimize_read_in_order=0;
|
||||
select x + y, sum(x - y) as s from test_agg_proj_02302 group by x + y order by s desc limit 5 settings allow_experimental_projection_optimization=1, optimize_aggregation_in_order=1, optimize_read_in_order=1;
|
||||
|
||||
-- { echoOff }
|
||||
drop table test_agg_proj_02302;
|
Loading…
Reference in New Issue
Block a user