Merge pull request #26657 from hexiaoting/fuse_quantile

This commit is contained in:
Vladimir C 2021-09-21 12:33:07 +03:00 committed by GitHub
commit bc7c41efff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 350 additions and 15 deletions

View File

@ -3343,7 +3343,7 @@ Result:
└─────┘
```
## optimize_fuse_sum_count_avg {#optimize_fuse_sum_count_avg}
## optimize_syntax_fuse_functions {#optimize_syntax_fuse_functions}
Enables to fuse aggregate functions with identical argument. It rewrites query contains at least two aggregate functions from [sum](../../sql-reference/aggregate-functions/reference/sum.md#agg_function-sum), [count](../../sql-reference/aggregate-functions/reference/count.md#agg_function-count) or [avg](../../sql-reference/aggregate-functions/reference/avg.md#agg_function-avg) with identical argument to [sumCount](../../sql-reference/aggregate-functions/reference/sumcount.md#agg_function-sumCount).
@ -3360,7 +3360,7 @@ Query:
``` sql
CREATE TABLE fuse_tbl(a Int8, b Int8) Engine = Log;
SET optimize_fuse_sum_count_avg = 1;
SET optimize_syntax_fuse_functions = 1;
EXPLAIN SYNTAX SELECT sum(a), sum(b), count(b), avg(b) from fuse_tbl FORMAT TSV;
```

View File

@ -43,4 +43,4 @@ Result:
**See also**
- [optimize_fuse_sum_count_avg](../../../operations/settings/settings.md#optimize_fuse_sum_count_avg) setting.
- [optimize_syntax_fuse_functions](../../../operations/settings/settings.md#optimize_syntax_fuse_functions) setting.

View File

@ -3122,7 +3122,7 @@ SELECT * FROM test LIMIT 10 OFFSET 100;
Значение по умолчанию: `1800`.
## optimize_fuse_sum_count_avg {#optimize_fuse_sum_count_avg}
## optimize_syntax_fuse_functions {#optimize_syntax_fuse_functions}
Позволяет объединить агрегатные функции с одинаковым аргументом. Запрос, содержащий по крайней мере две агрегатные функции: [sum](../../sql-reference/aggregate-functions/reference/sum.md#agg_function-sum), [count](../../sql-reference/aggregate-functions/reference/count.md#agg_function-count) или [avg](../../sql-reference/aggregate-functions/reference/avg.md#agg_function-avg) с одинаковым аргументом, перезаписывается как [sumCount](../../sql-reference/aggregate-functions/reference/sumcount.md#agg_function-sumCount).
@ -3139,7 +3139,7 @@ SELECT * FROM test LIMIT 10 OFFSET 100;
``` sql
CREATE TABLE fuse_tbl(a Int8, b Int8) Engine = Log;
SET optimize_fuse_sum_count_avg = 1;
SET optimize_syntax_fuse_functions = 1;
EXPLAIN SYNTAX SELECT sum(a), sum(b), count(b), avg(b) from fuse_tbl FORMAT TSV;
```

View File

@ -43,4 +43,4 @@ SELECT sumCount(x) from s_table;
**Смотрите также**
- Настройка [optimize_fuse_sum_count_avg](../../../operations/settings/settings.md#optimize_fuse_sum_count_avg)
- Настройка [optimize_syntax_fuse_functions](../../../operations/settings/settings.md#optimize_syntax_fuse_functions)

View File

@ -455,7 +455,7 @@ class IColumn;
M(Bool, allow_non_metadata_alters, true, "Allow to execute alters which affects not only tables metadata, but also data on disk", 0) \
M(Bool, enable_global_with_statement, true, "Propagate WITH statements to UNION queries and all subqueries", 0) \
M(Bool, aggregate_functions_null_for_empty, false, "Rewrite all aggregate functions in a query, adding -OrNull suffix to them", 0) \
M(Bool, optimize_fuse_sum_count_avg, false, "Fuse aggregate functions sum(), avg(), count() with identical arguments into one sumCount() call, if the query has at least two different functions", 0) \
M(Bool, optimize_syntax_fuse_functions, false, "Fuse aggregate functions (`sum, avg, count` with identical arguments into one `sumCount`, quantile-family functions with the same argument into `quantiles*(...)[...]`)", 0) \
M(Bool, flatten_nested, true, "If true, columns of type Nested will be flatten to separate array columns instead of one array of tuples", 0) \
M(Bool, asterisk_include_materialized_columns, false, "Include MATERIALIZED columns for wildcard query", 0) \
M(Bool, asterisk_include_alias_columns, false, "Include ALIAS columns for wildcard query", 0) \
@ -525,6 +525,7 @@ class IColumn;
M(HandleKafkaErrorMode, handle_kafka_error_mode, HandleKafkaErrorMode::DEFAULT, "Obsolete setting, does nothing.", 0) \
M(Bool, database_replicated_ddl_output, true, "Obsolete setting, does nothing.", 0) \
M(UInt64, replication_alter_columns_timeout, 60, "Obsolete setting, does nothing.", 0) \
M(Bool, optimize_fuse_sum_count_avg, false, "Obsolete, use optimize_syntax_fuse_functions", 0) \
/** The section above is for obsolete settings. Do not add anything there. */

View File

@ -0,0 +1,83 @@
#include <string>
#include <Interpreters/GatherFunctionQuantileVisitor.h>
#include <Common/Exception.h>
#include <common/types.h>
namespace DB
{
namespace ErrorCodes
{
extern const int LOGICAL_ERROR;
}
/// Mapping from quantile functions for single value to plural
static const std::unordered_map<String, String> quantile_fuse_name_mapping = {
{NameQuantile::name, NameQuantiles::name},
{NameQuantileDeterministic::name, NameQuantilesDeterministic::name},
{NameQuantileExact::name, NameQuantilesExact::name},
{NameQuantileExactLow::name, NameQuantilesExactLow::name},
{NameQuantileExactHigh::name, NameQuantilesExactHigh::name},
{NameQuantileExactExclusive::name, NameQuantilesExactExclusive::name},
{NameQuantileExactInclusive::name, NameQuantilesExactInclusive::name},
{NameQuantileExactWeighted::name, NameQuantilesExactWeighted::name},
{NameQuantileTiming::name, NameQuantilesTiming::name},
{NameQuantileTimingWeighted::name, NameQuantilesTimingWeighted::name},
{NameQuantileTDigest::name, NameQuantilesTDigest::name},
{NameQuantileTDigestWeighted::name, NameQuantilesTDigestWeighted::name},
{NameQuantileBFloat16::name, NameQuantilesBFloat16::name}
};
String GatherFunctionQuantileData::getFusedName(const String & func_name)
{
if (auto it = quantile_fuse_name_mapping.find(func_name); it != quantile_fuse_name_mapping.end())
return it->second;
throw DB::Exception(ErrorCodes::LOGICAL_ERROR, "Function '{}' is not quantile-family or cannot be fused", func_name);
}
void GatherFunctionQuantileData::visit(ASTFunction & function, ASTPtr & ast)
{
if (!quantile_fuse_name_mapping.contains(function.name))
return;
fuse_quantile[function.name].addFuncNode(ast);
}
void GatherFunctionQuantileData::FuseQuantileAggregatesData::addFuncNode(ASTPtr & ast)
{
const auto * func = ast->as<ASTFunction>();
if (!func)
return;
const auto & arguments = func->arguments->children;
bool need_two_args = func->name == NameQuantileDeterministic::name
|| func->name == NameQuantileExactWeighted::name
|| func->name == NameQuantileTimingWeighted::name
|| func->name == NameQuantileTDigestWeighted::name;
if (arguments.size() != (need_two_args ? 2 : 1))
return;
if (arguments[0]->getColumnName().find(',') != std::string::npos)
return;
String arg_name = arguments[0]->getColumnName();
if (need_two_args)
{
if (arguments[1]->getColumnName().find(',') != std::string::npos)
return;
arg_name += "," + arguments[1]->getColumnName();
}
arg_map_function[arg_name].push_back(&ast);
}
bool GatherFunctionQuantileData::needChild(const ASTPtr & node, const ASTPtr &)
{
/// Skip children of quantile* functions to escape cycles in further processing
if (const auto * func = node ? node->as<ASTFunction>() : nullptr)
return !quantile_fuse_name_mapping.contains(func->name);
return true;
}
}

View File

@ -0,0 +1,35 @@
#pragma once
#include <Parsers/ASTFunction.h>
#include <Parsers/IAST.h>
#include <Interpreters/InDepthNodeVisitor.h>
#include <AggregateFunctions/AggregateFunctionQuantile.h>
namespace DB
{
/// Gather all the `quantile*` functions
class GatherFunctionQuantileData
{
public:
struct FuseQuantileAggregatesData
{
std::unordered_map<String, std::vector<ASTPtr *>> arg_map_function;
void addFuncNode(ASTPtr & ast);
};
using TypeToVisit = ASTFunction;
std::unordered_map<String, FuseQuantileAggregatesData> fuse_quantile;
void visit(ASTFunction & function, ASTPtr & ast);
static String getFusedName(const String & func_name);
static bool needChild(const ASTPtr & node, const ASTPtr &);
};
using GatherFunctionQuantileVisitor = InDepthNodeVisitor<OneTypeMatcher<GatherFunctionQuantileData, GatherFunctionQuantileData::needChild>, true>;
}

View File

@ -18,6 +18,7 @@
#include <Interpreters/RewriteFunctionToSubcolumnVisitor.h>
#include <Interpreters/Context.h>
#include <Interpreters/ExternalDictionariesLoader.h>
#include <Interpreters/GatherFunctionQuantileVisitor.h>
#include <Parsers/ASTExpressionList.h>
#include <Parsers/ASTFunction.h>
@ -626,6 +627,59 @@ void optimizeFunctionsToSubcolumns(ASTPtr & query, const StorageMetadataPtr & me
RewriteFunctionToSubcolumnVisitor(data).visit(query);
}
std::shared_ptr<ASTFunction> getQuantileFuseCandidate(const String & func_name, std::vector<ASTPtr *> & functions)
{
if (functions.size() < 2)
return nullptr;
const auto & common_arguments = (*functions[0])->as<ASTFunction>()->arguments->children;
auto func_base = makeASTFunction(GatherFunctionQuantileData::getFusedName(func_name));
func_base->arguments->children = common_arguments;
func_base->parameters = std::make_shared<ASTExpressionList>();
for (const auto * ast : functions)
{
assert(ast && *ast);
const auto * func = (*ast)->as<ASTFunction>();
assert(func && func->parameters->as<ASTExpressionList>());
const ASTs & parameters = func->parameters->as<ASTExpressionList &>().children;
if (parameters.size() != 1)
return nullptr; /// query is illegal, give up
func_base->parameters->children.push_back(parameters[0]);
}
return func_base;
}
/// Rewrites multi quantile()() functions with the same arguments to quantiles()()[]
/// eg:SELECT quantile(0.5)(x), quantile(0.9)(x), quantile(0.95)(x) FROM...
/// rewrite to : SELECT quantiles(0.5, 0.9, 0.95)(x)[1], quantiles(0.5, 0.9, 0.95)(x)[2], quantiles(0.5, 0.9, 0.95)(x)[3] FROM ...
void optimizeFuseQuantileFunctions(ASTPtr & query)
{
GatherFunctionQuantileVisitor::Data data{};
GatherFunctionQuantileVisitor(data).visit(query);
for (auto & candidate : data.fuse_quantile)
{
String func_name = candidate.first;
auto & args_to_functions = candidate.second;
/// Try to fuse multiply `quantile*` Function to plural
for (auto it : args_to_functions.arg_map_function)
{
std::vector<ASTPtr *> & functions = it.second;
auto func_base = getQuantileFuseCandidate(func_name, functions);
if (!func_base)
continue;
for (size_t i = 0; i < functions.size(); ++i)
{
std::shared_ptr<ASTFunction> ast_new = makeASTFunction("arrayElement", func_base, std::make_shared<ASTLiteral>(i + 1));
if (const auto & alias = (*functions[i])->tryGetAlias(); !alias.empty())
ast_new->setAlias(alias);
*functions[i] = ast_new;
}
}
}
}
}
void TreeOptimizer::optimizeIf(ASTPtr & query, Aliases & aliases, bool if_chain_to_multiif)
@ -723,6 +777,9 @@ void TreeOptimizer::apply(ASTPtr & query, TreeRewriterResult & result,
/// Remove duplicated columns from USING(...).
optimizeUsing(select_query);
if (settings.optimize_syntax_fuse_functions)
optimizeFuseQuantileFunctions(query);
}
}

View File

@ -1072,7 +1072,7 @@ void TreeRewriter::normalize(
// if we have at least two different functions. E.g. we will replace sum(x)
// and count(x) with sumCount(x).1 and sumCount(x).2, and sumCount() will
// be calculated only once because of CSE.
if (settings.optimize_fuse_sum_count_avg)
if (settings.optimize_fuse_sum_count_avg || settings.optimize_syntax_fuse_functions)
{
FuseSumCountAggregatesVisitor::Data data;
FuseSumCountAggregatesVisitor(data).visit(query);

View File

@ -64,6 +64,7 @@ SRCS(
ExtractExpressionInfoVisitor.cpp
FillingRow.cpp
FunctionNameNormalizer.cpp
GatherFunctionQuantileVisitor.cpp
HashJoin.cpp
IExternalLoadable.cpp
IInterpreter.cpp

View File

@ -6,7 +6,7 @@
Also test GROUP BY with and without keys, because they might have different
optimizations. -->
<settings>
<optimize_fuse_sum_count_avg>1</optimize_fuse_sum_count_avg>
<optimize_syntax_fuse_functions>1</optimize_syntax_fuse_functions>
</settings>
<substitutions>
@ -21,13 +21,13 @@
<query>SELECT sum(number) FROM numbers(1000000000) FORMAT Null</query>
<query>SELECT sum(number), count(number) FROM numbers(1000000000) FORMAT Null</query>
<query>SELECT sum(number), count(number) FROM numbers(1000000000) SETTINGS optimize_fuse_sum_count_avg = 0 FORMAT Null</query>
<query>SELECT sum(number), count(number) FROM numbers(1000000000) SETTINGS optimize_syntax_fuse_functions = 0 FORMAT Null</query>
<query>SELECT sum(number), avg(number), count(number) FROM numbers(1000000000) FORMAT Null</query>
<query>SELECT sum(number), avg(number), count(number) FROM numbers(1000000000) SETTINGS optimize_fuse_sum_count_avg = 0 FORMAT Null</query>
<query>SELECT sum(number), avg(number), count(number) FROM numbers(1000000000) SETTINGS optimize_syntax_fuse_functions = 0 FORMAT Null</query>
<query>SELECT sum(number) FROM numbers(100000000) GROUP BY intHash32(number) % 1000 FORMAT Null</query>
<query>SELECT sum(number), count(number) FROM numbers(100000000) GROUP BY intHash32(number) % 1000 FORMAT Null</query>
<query>SELECT sum(number), count(number) FROM numbers(100000000) GROUP BY intHash32(number) % 1000 SETTINGS optimize_fuse_sum_count_avg = 0 FORMAT Null</query>
<query>SELECT sum(number), count(number) FROM numbers(100000000) GROUP BY intHash32(number) % 1000 SETTINGS optimize_syntax_fuse_functions = 0 FORMAT Null</query>
<query>SELECT sum(number), avg(number), count(number) FROM numbers(100000000) GROUP BY intHash32(number) % 1000 FORMAT Null</query>
<query>SELECT sum(number), avg(number), count(number) FROM numbers(100000000) GROUP BY intHash32(number) % 1000 SETTINGS optimize_fuse_sum_count_avg = 0 FORMAT Null</query>
<query>SELECT sum(number), avg(number), count(number) FROM numbers(100000000) GROUP BY intHash32(number) % 1000 SETTINGS optimize_syntax_fuse_functions = 0 FORMAT Null</query>
</test>

View File

@ -2,7 +2,7 @@ DROP TABLE IF EXISTS fuse_tbl;
CREATE TABLE fuse_tbl(a Int8, b Int8) Engine = Log;
INSERT INTO fuse_tbl SELECT number, number + 1 FROM numbers(1, 20);
SET optimize_fuse_sum_count_avg = 1;
SET optimize_syntax_fuse_functions = 1;
SELECT sum(a), sum(b), count(b) from fuse_tbl;
EXPLAIN SYNTAX SELECT sum(a), sum(b), count(b) from fuse_tbl;
SELECT '---------NOT trigger fuse--------';

View File

@ -0,0 +1,90 @@
2016-06-15 23:00:00 2016-06-15 23:00:00
2016-06-15 23:00:00 2016-06-15 23:00:00
2016-06-15 23:00:00 2016-06-15 23:00:00
2016-06-15 23:00:00 2016-06-15 23:00:00 2016-06-15 23:00:00
30000 30000 30000
30000 30000 30000
2016-06-15 23:00:16 2016-06-15 23:00:16 2016-06-15 23:00:16
2016-06-15 23:00:16 2016-06-15 23:00:16 2016-06-15 23:00:16
2016-04-02 17:23:12 2016-04-02 17:23:12 2016-04-02 17:23:12
---------After fuse result-----------
quantile:
SELECT
quantiles(0.2, 0.3)(d)[1],
quantiles(0.2, 0.3)(d)[2]
FROM datetime
2016-06-15 23:00:00 2016-06-15 23:00:00
quantileDeterministic:
SELECT
quantilesDeterministic(0.2, 0.5)(d, 1)[1],
quantilesDeterministic(0.2, 0.5)(d, 1)[2]
FROM datetime
2016-06-15 23:00:00 2016-06-15 23:00:00
quantileExact:
SELECT
quantilesExact(0.2, 0.5)(d)[1],
quantilesExact(0.2, 0.5)(d)[2]
FROM datetime
2016-06-15 23:00:00 2016-06-15 23:00:00
quantileExactWeighted:
SELECT
quantilesExactWeighted(0.2, 0.4)(d, 1)[1],
quantilesExactWeighted(0.2, 0.4)(d, 1)[2],
quantileExactWeighted(0.3)(d, 2)
FROM datetime
2016-06-15 23:00:00 2016-06-15 23:00:00 2016-06-15 23:00:00
quantileTiming:
SELECT
quantilesTiming(0.2, 0.3)(d)[1],
quantilesTiming(0.2, 0.3)(d)[2],
quantileTiming(0.2)(d + 1)
FROM datetime
30000 30000 30000
quantileTimingWeighted:
SELECT
quantilesTimingWeighted(0.2, 0.3)(d, 1)[1],
quantilesTimingWeighted(0.2, 0.3)(d, 1)[2],
quantileTimingWeighted(0.2)(d, 2)
FROM datetime
30000 30000 30000
quantileTDigest:
SELECT
quantilesTDigest(0.2, 0.3)(d)[1],
quantilesTDigest(0.2, 0.3)(d)[2],
quantileTDigest(0.2)(d + 1)
FROM datetime
2016-06-15 23:00:16 2016-06-15 23:00:16 2016-06-15 23:00:16
quantileTDigestWeighted:
SELECT
quantilesTDigestWeighted(0.2, 0.3)(d, 1)[1],
quantilesTDigestWeighted(0.2, 0.3)(d, 1)[2],
quantileTDigestWeighted(0.4)(d, 2)
FROM datetime
2016-06-15 23:00:16 2016-06-15 23:00:16 2016-06-15 23:00:16
quantileBFloat16:
SELECT
quantilesBFloat16(0.2, 0.3)(d)[1],
quantilesBFloat16(0.2, 0.3)(d)[2],
quantileBFloat16(0.4)(d + 1)
FROM datetime
2016-04-02 17:23:12 2016-04-02 17:23:12 2016-04-02 17:23:12
SELECT
quantiles(0.2, 0.3, 0.2)(d)[1] AS k,
quantiles(0.2, 0.3, 0.2)(d)[2]
FROM datetime
ORDER BY quantiles(0.2, 0.3, 0.2)(d)[3] ASC
0 4 7.2 7.6
1 5 8.2 8.6
SELECT
b,
quantiles(0.5, 0.9, 0.95)(x)[1] AS a,
quantiles(0.5, 0.9, 0.95)(x)[2] AS y,
quantiles(0.5, 0.9, 0.95)(x)[3]
FROM
(
SELECT
number AS x,
number % 2 AS b
FROM numbers(10)
)
GROUP BY b

View File

@ -0,0 +1,68 @@
DROP TABLE IF EXISTS datetime;
CREATE TABLE datetime (d DateTime('UTC')) ENGINE = Memory;
INSERT INTO datetime(d) VALUES(toDateTime('2016-06-15 23:00:00', 'UTC'))
SELECT quantile(0.2)(d), quantile(0.3)(d) FROM datetime;
SELECT quantileDeterministic(0.2)(d, 1), quantileDeterministic(0.5)(d, 1) FROM datetime;
SELECT quantileExact(0.2)(d), quantileExact(0.5)(d) FROM datetime;
SELECT quantileExactWeighted(0.2)(d, 1), quantileExactWeighted(0.4)(d, 1), quantileExactWeighted(0.3)(d, 2) FROM datetime;
SELECT quantileTiming(0.2)(d), quantileTiming(0.3)(d), quantileTiming(0.2)(d+1) FROM datetime;
SELECT quantileTimingWeighted(0.2)(d, 1), quantileTimingWeighted(0.3)(d, 1), quantileTimingWeighted(0.2)(d, 2) FROM datetime;
SELECT quantileTDigest(0.2)(d), quantileTDigest(0.3)(d), quantileTDigest(0.2)(d + 1) FROM datetime;
SELECT quantileTDigestWeighted(0.2)(d, 1), quantileTDigestWeighted(0.3)(d, 1), quantileTDigestWeighted(0.4)(d, 2) FROM datetime;
SELECT quantileBFloat16(0.2)(d), quantileBFloat16(0.3)(d), quantileBFloat16(0.4)(d + 1) FROM datetime;
SELECT '---------After fuse result-----------';
SET optimize_syntax_fuse_functions = true;
SELECT 'quantile:';
EXPLAIN SYNTAX SELECT quantile(0.2)(d), quantile(0.3)(d) FROM datetime;
SELECT quantile(0.2)(d), quantile(0.3)(d) FROM datetime;
SELECT 'quantileDeterministic:';
EXPLAIN SYNTAX SELECT quantileDeterministic(0.2)(d, 1), quantileDeterministic(0.5)(d, 1) FROM datetime;
SELECT quantileDeterministic(0.2)(d, 1), quantileDeterministic(0.5)(d, 1) FROM datetime;
SELECT 'quantileExact:';
EXPLAIN SYNTAX SELECT quantileExact(0.2)(d), quantileExact(0.5)(d) FROM datetime;
SELECT quantileExact(0.2)(d), quantileExact(0.5)(d) FROM datetime;
SELECT 'quantileExactWeighted:';
EXPLAIN SYNTAX SELECT quantileExactWeighted(0.2)(d, 1), quantileExactWeighted(0.4)(d, 1), quantileExactWeighted(0.3)(d, 2) FROM datetime;
SELECT quantileExactWeighted(0.2)(d, 1), quantileExactWeighted(0.4)(d, 1), quantileExactWeighted(0.3)(d, 2) FROM datetime;
SELECT 'quantileTiming:';
EXPLAIN SYNTAX SELECT quantileTiming(0.2)(d), quantileTiming(0.3)(d), quantileTiming(0.2)(d+1) FROM datetime;
SELECT quantileTiming(0.2)(d), quantileTiming(0.3)(d), quantileTiming(0.2)(d+1) FROM datetime;
SELECT 'quantileTimingWeighted:';
EXPLAIN SYNTAX SELECT quantileTimingWeighted(0.2)(d, 1), quantileTimingWeighted(0.3)(d, 1), quantileTimingWeighted(0.2)(d, 2) FROM datetime;
SELECT quantileTimingWeighted(0.2)(d, 1), quantileTimingWeighted(0.3)(d, 1), quantileTimingWeighted(0.2)(d, 2) FROM datetime;
SELECT 'quantileTDigest:';
EXPLAIN SYNTAX SELECT quantileTDigest(0.2)(d), quantileTDigest(0.3)(d), quantileTDigest(0.2)(d + 1) FROM datetime;
SELECT quantileTDigest(0.2)(d), quantileTDigest(0.3)(d), quantileTDigest(0.2)(d + 1) FROM datetime;
SELECT 'quantileTDigestWeighted:';
EXPLAIN SYNTAX SELECT quantileTDigestWeighted(0.2)(d, 1), quantileTDigestWeighted(0.3)(d, 1), quantileTDigestWeighted(0.4)(d, 2) FROM datetime;
SELECT quantileTDigestWeighted(0.2)(d, 1), quantileTDigestWeighted(0.3)(d, 1), quantileTDigestWeighted(0.4)(d, 2) FROM datetime;
SELECT 'quantileBFloat16:';
EXPLAIN SYNTAX SELECT quantileBFloat16(0.2)(d), quantileBFloat16(0.3)(d), quantileBFloat16(0.4)(d + 1) FROM datetime;
SELECT quantileBFloat16(0.2)(d), quantileBFloat16(0.3)(d), quantileBFloat16(0.4)(d + 1) FROM datetime;
EXPLAIN SYNTAX SELECT quantile(0.2)(d) as k, quantile(0.3)(d) FROM datetime order by quantile(0.2)(d);
SELECT b, quantile(0.5)(x) as a, quantile(0.9)(x) as y, quantile(0.95)(x) FROM (select number as x, number % 2 as b from numbers(10)) group by b;
EXPLAIN SYNTAX SELECT b, quantile(0.5)(x) as a, quantile(0.9)(x) as y, quantile(0.95)(x) FROM (select number as x, number % 2 as b from numbers(10)) group by b;
-- fuzzer
SELECT quantileDeterministic(0.99)(1023) FROM datetime FORMAT Null; -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
SELECT quantileTiming(0.5)(NULL, NULL, quantileTiming(-inf)(NULL), NULL) FROM datetime FORMAT Null; -- { serverError ILLEGAL_AGGREGATION }
SELECT quantileTDigest(NULL)(NULL, quantileTDigest(3.14)(NULL, d + NULL), 2.), NULL FORMAT Null; -- { serverError ILLEGAL_AGGREGATION }
SELECT quantile(1, 0.3)(d), quantile(0.3)(d) FROM datetime; -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
SELECT quantile(quantileDeterministic('', '2.47')('0.02', '0.2', NULL), 0.9)(d), quantile(0.3)(d) FROM datetime; -- { serverError ILLEGAL_AGGREGATION }
SELECT quantileTimingWeighted([[[[['-214748364.8'], NULL]], [[[quantileTimingWeighted([[[[['-214748364.8'], NULL], '-922337203.6854775808'], [[['-214748364.7']]], NULL]])([NULL], NULL), '-214748364.7']]], NULL]])([NULL], NULL); -- { serverError ILLEGAL_AGGREGATION }
SELECT quantileTimingWeighted([quantileTimingWeighted(0.5)(1, 1)])(1, 1); -- { serverError ILLEGAL_AGGREGATION }
DROP TABLE datetime;