Support TotalsHaving. Update test.

This commit is contained in:
Nikolai Kochetov 2021-02-18 16:13:09 +03:00
parent 7231a97085
commit 0449546bca
4 changed files with 56 additions and 5 deletions

View File

@ -5,14 +5,17 @@
#include <Processors/QueryPlan/ExpressionStep.h>
#include <Processors/QueryPlan/ArrayJoinStep.h>
#include <Processors/QueryPlan/CubeStep.h>
#include <Processors/QueryPlan/FinishSortingStep.h>
#include <Processors/QueryPlan/MergeSortingStep.h>
#include <Processors/QueryPlan/MergingSortedStep.h>
#include <Processors/QueryPlan/PartialSortingStep.h>
#include <Processors/QueryPlan/TotalsHavingStep.h>
#include <Processors/QueryPlan/DistinctStep.h>
#include <Interpreters/ActionsDAG.h>
#include <Interpreters/ArrayJoinAction.h>
#include <Common/typeid_cast.h>
#include "Processors/QueryPlan/FinishSortingStep.h"
#include "Processors/QueryPlan/MergeSortingStep.h"
#include "Processors/QueryPlan/MergingSortedStep.h"
#include "Processors/QueryPlan/PartialSortingStep.h"
#include <Processors/QueryPlan/DistinctStep.h>
#include <DataTypes/DataTypeAggregateFunction.h>
#include <Columns/IColumn.h>
namespace DB::ErrorCodes
@ -135,6 +138,31 @@ size_t tryPushDownFilter(QueryPlan::Node * parent_node, QueryPlan::Nodes & nodes
return updated_steps;
}
if (auto * totals_having = typeid_cast<TotalsHavingStep *>(child.get()))
{
/// If totals step has HAVING expression, skip it for now.
/// TODO:
/// We can merge HAING expression with current filer.
/// Alos, we can push down part of HAVING which depend only on aggregation keys.
if (totals_having->getActions())
return 0;
Names keys;
const auto & header = totals_having->getInputStreams().front().header;
for (const auto & column : header)
if (typeid_cast<const DataTypeAggregateFunction *>(column.type.get()) == nullptr)
keys.push_back(column.name);
/// NOTE: this optimization changes TOTALS value. Example:
/// `select * from (select y, sum(x) from (
/// select number as x, number % 4 as y from numbers(10)
/// ) group by y with totals) where y != 2`
/// Optimization will replace totals row `y, sum(x)` from `(0, 45)` to `(0, 37)`.
/// It is expected to ok, cause AST optimization `enable_optimize_predicate_expression = 1` also brakes it.
if (auto updated_steps = tryAddNewFilterStep(parent_node, nodes, keys))
return updated_steps;
}
if (auto * array_join = typeid_cast<ArrayJoinStep *>(child.get()))
{
const auto & array_join_actions = array_join->arrayJoin();

View File

@ -28,6 +28,8 @@ public:
void describeActions(FormatSettings & settings) const override;
const ActionsDAGPtr & getActions() const { return actions_dag; }
private:
bool overflow_row;
ActionsDAGPtr actions_dag;

View File

@ -112,3 +112,12 @@ PartialSorting
Filter column: and(notEquals(x, 0), notEquals(y, 0))
1 2
1 1
> filter is pushed down before TOTALS HAVING and aggregating
TotalsHaving
Aggregating
Filter column: notEquals(y, 2)
0 12
1 15
3 10
0 37

View File

@ -135,3 +135,15 @@ $CLICKHOUSE_CLIENT -q "
select number % 2 as x, number % 3 as y from numbers(6) order by y desc
) where x != 0 and y != 0
settings enable_optimize_predicate_expression = 0"
echo "> filter is pushed down before TOTALS HAVING and aggregating"
$CLICKHOUSE_CLIENT -q "
explain actions = 1 select * from (
select y, sum(x) from (select number as x, number % 4 as y from numbers(10)) group by y with totals
) where y != 2
settings enable_optimize_predicate_expression=0" |
grep -o "TotalsHaving\|Aggregating\|Filter column: notEquals(y, 2)"
$CLICKHOUSE_CLIENT -q "
select * from (
select y, sum(x) from (select number as x, number % 4 as y from numbers(10)) group by y with totals
) where y != 2"