From b1d47ac83de87b52c6e52120e0aa1145567aa485 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 16 Dec 2024 14:40:08 +0100 Subject: [PATCH] Vectorize aggregate FILTER clause (#7458) Support vecorized aggregation with aggregate FILTER clauses that are also vectorizable --- .unreleased/vectorized-agg-filter | 1 + tsl/src/compression/arrow_c_data_interface.h | 58 +- .../nodes/decompress_chunk/compressed_batch.c | 16 +- .../nodes/decompress_chunk/compressed_batch.h | 16 + tsl/src/nodes/decompress_chunk/planner.c | 6 - tsl/src/nodes/vector_agg/exec.c | 50 + tsl/src/nodes/vector_agg/exec.h | 2 + .../nodes/vector_agg/grouping_policy_batch.c | 18 +- tsl/src/nodes/vector_agg/plan.c | 184 +- tsl/test/expected/vector_agg_filter.out | 2965 +++++++++++++++++ tsl/test/expected/vectorized_aggregation.out | 56 +- tsl/test/sql/CMakeLists.txt | 1 + tsl/test/sql/vector_agg_filter.sql | 121 + tsl/test/sql/vectorized_aggregation.sql | 4 +- 14 files changed, 3390 insertions(+), 108 deletions(-) create mode 100644 .unreleased/vectorized-agg-filter create mode 100644 tsl/test/expected/vector_agg_filter.out create mode 100644 tsl/test/sql/vector_agg_filter.sql diff --git a/.unreleased/vectorized-agg-filter b/.unreleased/vectorized-agg-filter new file mode 100644 index 00000000000..79b88afb3db --- /dev/null +++ b/.unreleased/vectorized-agg-filter @@ -0,0 +1 @@ +Implements: #7458 Support vecorized aggregation with aggregate FILTER clauses that are also vectorizable diff --git a/tsl/src/compression/arrow_c_data_interface.h b/tsl/src/compression/arrow_c_data_interface.h index 1473e24945b..a1f989c99e2 100644 --- a/tsl/src/compression/arrow_c_data_interface.h +++ b/tsl/src/compression/arrow_c_data_interface.h @@ -184,25 +184,73 @@ arrow_set_row_validity(uint64 *bitmap, size_t row_number, bool value) } /* - * AND two optional arrow validity bitmaps into the given storage. + * Combine the validity bitmaps into the given storage. */ static inline const uint64 * arrow_combine_validity(size_t num_words, uint64 *restrict storage, const uint64 *filter1, - const uint64 *filter2) + const uint64 *filter2, const uint64 *filter3) { + /* + * Any and all of the filters can be null. For simplicity, move the non-null + * filters to the leading positions. + */ + const uint64 *tmp; +#define SWAP(X, Y) \ + tmp = (X); \ + (X) = (Y); \ + (Y) = tmp; + if (filter1 == NULL) { - return filter2; + /* + * We have at least one NULL that goes to the last position. + */ + SWAP(filter1, filter3); + + if (filter1 == NULL) + { + /* + * We have another NULL that goes to the second position. + */ + SWAP(filter1, filter2); + } } + else + { + if (filter2 == NULL) + { + /* + * We have at least one NULL that goes to the last position. + */ + SWAP(filter2, filter3); + } + } +#undef SWAP + + Assert(filter2 == NULL || filter1 != NULL); + Assert(filter3 == NULL || filter2 != NULL); if (filter2 == NULL) { + /* Either have one non-null filter, or all of them are null. */ return filter1; } - for (size_t i = 0; i < num_words; i++) + if (filter3 == NULL) + { + /* Have two non-null filters. */ + for (size_t i = 0; i < num_words; i++) + { + storage[i] = filter1[i] & filter2[i]; + } + } + else { - storage[i] = filter1[i] & filter2[i]; + /* Have three non-null filters. */ + for (size_t i = 0; i < num_words; i++) + { + storage[i] = filter1[i] & filter2[i] & filter3[i]; + } } return storage; diff --git a/tsl/src/nodes/decompress_chunk/compressed_batch.c b/tsl/src/nodes/decompress_chunk/compressed_batch.c index 81ed77fa8e0..582df8cbc1b 100644 --- a/tsl/src/nodes/decompress_chunk/compressed_batch.c +++ b/tsl/src/nodes/decompress_chunk/compressed_batch.c @@ -20,18 +20,6 @@ #include "nodes/decompress_chunk/vector_predicates.h" #include "nodes/decompress_chunk/vector_quals.h" -/* - * VectorQualState for a compressed batch used to pass - * DecompressChunk-specific data to vector qual functions that are shared - * across scan nodes. - */ -typedef struct CompressedBatchVectorQualState -{ - VectorQualState vqstate; - DecompressBatchState *batch_state; - DecompressContext *dcontext; -} CompressedBatchVectorQualState; - /* * Create a single-value ArrowArray of an arithmetic type. This is a specialized * function because arithmetic types have a particular layout of ArrowArrays. @@ -312,7 +300,7 @@ decompress_column(DecompressContext *dcontext, DecompressBatchState *batch_state * VectorQualState->get_arrow_array() function used to interface with the * vector qual code across different scan nodes. */ -static const ArrowArray * +const ArrowArray * compressed_batch_get_arrow_array(VectorQualState *vqstate, Expr *expr, bool *is_default_value) { CompressedBatchVectorQualState *cbvqstate = (CompressedBatchVectorQualState *) vqstate; @@ -360,8 +348,6 @@ compressed_batch_get_arrow_array(VectorQualState *vqstate, Expr *expr, bool *is_ var->varattno); Assert(column_description != NULL); Assert(column_description->typid == var->vartype); - Ensure(column_description->type == COMPRESSED_COLUMN, - "only compressed columns are supported in vectorized quals"); CompressedColumnValues *column_values = &batch_state->compressed_columns[column_index]; diff --git a/tsl/src/nodes/decompress_chunk/compressed_batch.h b/tsl/src/nodes/decompress_chunk/compressed_batch.h index 3131c2c7fd2..9871503e37c 100644 --- a/tsl/src/nodes/decompress_chunk/compressed_batch.h +++ b/tsl/src/nodes/decompress_chunk/compressed_batch.h @@ -7,6 +7,7 @@ #include "compression/compression.h" #include "nodes/decompress_chunk/decompress_context.h" +#include "nodes/decompress_chunk/vector_quals.h" #include typedef struct ArrowArray ArrowArray; @@ -172,3 +173,18 @@ compressed_batch_current_tuple(DecompressBatchState *batch_state) Assert(batch_state->per_batch_context != NULL); return &batch_state->decompressed_scan_slot_data.base; } + +/* + * VectorQualState for a compressed batch used to pass + * DecompressChunk-specific data to vector qual functions that are shared + * across scan nodes. + */ +typedef struct CompressedBatchVectorQualState +{ + VectorQualState vqstate; + DecompressBatchState *batch_state; + DecompressContext *dcontext; +} CompressedBatchVectorQualState; + +const ArrowArray *compressed_batch_get_arrow_array(VectorQualState *vqstate, Expr *expr, + bool *is_default_value); diff --git a/tsl/src/nodes/decompress_chunk/planner.c b/tsl/src/nodes/decompress_chunk/planner.c index 8048fc2ceac..785b846e583 100644 --- a/tsl/src/nodes/decompress_chunk/planner.c +++ b/tsl/src/nodes/decompress_chunk/planner.c @@ -148,12 +148,6 @@ typedef struct } DecompressionMapContext; -typedef struct VectorQualInfoDecompressChunk -{ - VectorQualInfo vqinfo; - const UncompressedColumnInfo *colinfo; -} VectorQualInfoDecompressChunk; - static bool * build_vector_attrs_array(const UncompressedColumnInfo *colinfo, const CompressionInfo *info) { diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 1d773ce1c4e..68b6c244a05 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "nodes/vector_agg/exec.h" @@ -18,6 +19,7 @@ #include "guc.h" #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/decompress_chunk/exec.h" +#include "nodes/decompress_chunk/vector_quals.h" #include "nodes/vector_agg.h" static int @@ -67,6 +69,17 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) DecompressChunkState *decompress_state = (DecompressChunkState *) linitial(vector_agg_state->custom.custom_ps); + /* + * Set up the helper structures used to evaluate stable expressions in + * vectorized FILTER clauses. + */ + PlannerGlobal glob = { + .boundParams = node->ss.ps.state->es_param_list_info, + }; + PlannerInfo root = { + .glob = &glob, + }; + /* * The aggregated targetlist with Aggrefs is in the custom scan targetlist * of the custom scan node that is performing the vectorized aggregation. @@ -149,6 +162,12 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) { def->input_offset = -1; } + + if (aggref->aggfilter != NULL) + { + Node *constified = estimate_expression_value(&root, (Node *) aggref->aggfilter); + def->filter_clauses = list_make1(constified); + } } else { @@ -293,6 +312,37 @@ vector_agg_exec(CustomScanState *node) dcontext->ps->instrument->tuplecount += not_filtered_rows; } + /* + * Compute the vectorized filters for the aggregate function FILTER + * clauses. + */ + const int naggs = vector_agg_state->num_agg_defs; + for (int i = 0; i < naggs; i++) + { + VectorAggDef *agg_def = &vector_agg_state->agg_defs[i]; + if (agg_def->filter_clauses == NIL) + { + continue; + } + CompressedBatchVectorQualState cbvqstate = { + .vqstate = { + .vectorized_quals_constified = agg_def->filter_clauses, + .num_results = batch_state->total_batch_rows, + .per_vector_mcxt = batch_state->per_batch_context, + .slot = compressed_slot, + .get_arrow_array = compressed_batch_get_arrow_array, + }, + .batch_state = batch_state, + .dcontext = dcontext, + }; + VectorQualState *vqstate = &cbvqstate.vqstate; + vector_qual_compute(vqstate); + agg_def->filter_result = vqstate->vector_qual_result; + } + + /* + * Finally, pass the compressed batch to the grouping policy. + */ grouping->gp_add_batch(grouping, batch_state); } diff --git a/tsl/src/nodes/vector_agg/exec.h b/tsl/src/nodes/vector_agg/exec.h index 26f832b3548..e5e9775ebb9 100644 --- a/tsl/src/nodes/vector_agg/exec.h +++ b/tsl/src/nodes/vector_agg/exec.h @@ -18,6 +18,8 @@ typedef struct VectorAggDef VectorAggFunctions func; int input_offset; int output_offset; + List *filter_clauses; + uint64 *filter_result; } VectorAggDef; typedef struct GroupingColumn diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index c9fa8f66709..c9b4249c3f4 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -151,6 +151,7 @@ compute_single_aggregate(GroupingPolicyBatch *policy, DecompressBatchState *batc const uint64 *filter = arrow_combine_validity(num_words, policy->tmp_filter, batch_state->vector_qual_result, + agg_def->filter_result, arg_validity_bitmap); /* @@ -166,15 +167,16 @@ compute_single_aggregate(GroupingPolicyBatch *policy, DecompressBatchState *batc /* * Scalar argument, or count(*). Have to also count the valid rows in * the batch. - */ - const int n = arrow_num_valid(filter, batch_state->total_batch_rows); - - /* + * * The batches that are fully filtered out by vectorized quals should - * have been skipped by the caller. + * have been skipped by the caller, but we also have to check for the + * case when no rows match the aggregate FILTER clause. */ - Assert(n > 0); - agg_def->func.agg_scalar(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); + const int n = arrow_num_valid(filter, batch_state->total_batch_rows); + if (n > 0) + { + agg_def->func.agg_scalar(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); + } } } @@ -185,7 +187,7 @@ gp_batch_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) /* * Allocate the temporary filter array for computing the combined results of - * batch filter and column validity. + * batch filter, aggregate filter and column validity. */ const size_t num_words = (batch_state->total_batch_rows + 63) / 64; if (num_words > policy->num_tmp_filter_words) diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 210b3f322a2..d68376eef14 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -17,6 +17,7 @@ #include "exec.h" #include "nodes/decompress_chunk/planner.h" +#include "nodes/decompress_chunk/vector_quals.h" #include "nodes/vector_agg.h" #include "utils.h" @@ -181,6 +182,69 @@ vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk, List *resolved_ta return (Plan *) vector_agg; } +/* + * Map the custom scan attribute number to the uncompressed chunk attribute + * number. + */ +static int +custom_scan_to_uncompressed_chunk_attno(List *custom_scan_tlist, int custom_scan_attno) +{ + if (custom_scan_tlist == NIL) + { + return custom_scan_attno; + } + + Var *var = + castNode(Var, + castNode(TargetEntry, + list_nth(custom_scan_tlist, AttrNumberGetAttrOffset(custom_scan_attno))) + ->expr); + return var->varattno; +} + +/* + * Whether the given compressed column index corresponds to a vector variable. + */ +static bool +is_vector_compressed_column(CustomScan *custom, int compressed_column_index, bool *out_is_segmentby) +{ + List *bulk_decompression_column = list_nth(custom->custom_private, DCP_BulkDecompressionColumn); + const bool bulk_decompression_enabled_for_column = + list_nth_int(bulk_decompression_column, compressed_column_index); + + /* + * Bulk decompression can be disabled for all columns in the DecompressChunk + * node settings, we can't do vectorized aggregation for compressed columns + * in that case. For segmentby columns it's still possible. + */ + List *settings = linitial(custom->custom_private); + const bool bulk_decompression_enabled_globally = + list_nth_int(settings, DCS_EnableBulkDecompression); + + /* + * Check if this column is a segmentby. + */ + List *is_segmentby_column = list_nth(custom->custom_private, DCP_IsSegmentbyColumn); + const bool is_segmentby = list_nth_int(is_segmentby_column, compressed_column_index); + if (out_is_segmentby) + { + *out_is_segmentby = is_segmentby; + } + + /* + * We support vectorized aggregation either for segmentby columns or for + * columns with bulk decompression enabled. + */ + if (!is_segmentby && + !(bulk_decompression_enabled_for_column && bulk_decompression_enabled_globally)) + { + /* Vectorized aggregation not possible for this particular column. */ + return false; + } + + return true; +} + /* * Whether the expression can be used for vectorized processing: must be a Var * that refers to either a bulk-decompressed or a segmentby column. @@ -229,20 +293,8 @@ is_vector_var(CustomScan *custom, Expr *expr, bool *out_is_segmentby) continue; } - int uncompressed_chunk_attno = 0; - if (custom->custom_scan_tlist == NIL) - { - uncompressed_chunk_attno = custom_scan_attno; - } - else - { - Var *var = castNode(Var, - castNode(TargetEntry, - list_nth(custom->custom_scan_tlist, - AttrNumberGetAttrOffset(custom_scan_attno))) - ->expr); - uncompressed_chunk_attno = var->varattno; - } + const int uncompressed_chunk_attno = + custom_scan_to_uncompressed_chunk_attno(custom->custom_scan_tlist, custom_scan_attno); if (uncompressed_chunk_attno == decompressed_var->varattno) { @@ -250,55 +302,75 @@ is_vector_var(CustomScan *custom, Expr *expr, bool *out_is_segmentby) } } Ensure(compressed_column_index < list_length(decompression_map), "compressed column not found"); + return is_vector_compressed_column(custom, compressed_column_index, out_is_segmentby); +} - List *bulk_decompression_column = list_nth(custom->custom_private, DCP_BulkDecompressionColumn); - Assert(list_length(decompression_map) == list_length(bulk_decompression_column)); - const bool bulk_decompression_enabled_for_column = - list_nth_int(bulk_decompression_column, compressed_column_index); +/* + * Build supplementary info to determine whether we can vectorize the + * aggregate FILTER clauses. + */ +static VectorQualInfo +build_aggfilter_vector_qual_info(CustomScan *custom) +{ + VectorQualInfo vqi = { .rti = custom->scan.scanrelid }; /* - * Bulk decompression can be disabled for all columns in the DecompressChunk - * node settings, we can't do vectorized aggregation for compressed columns - * in that case. For segmentby columns it's still possible. + * Now, we have to translate the decompressed varno into the compressed + * column index, to check if the column supports bulk decompression. */ - List *settings = linitial(custom->custom_private); - const bool bulk_decompression_enabled_globally = - list_nth_int(settings, DCS_EnableBulkDecompression); + List *decompression_map = list_nth(custom->custom_private, DCP_DecompressionMap); /* - * Check if this column is a segmentby. + * There's no easy way to determine maximum attribute number for uncompressed + * chunk at this stage, so we'll have to go through all the compressed columns + * for this. */ - List *is_segmentby_column = list_nth(custom->custom_private, DCP_IsSegmentbyColumn); - Assert(list_length(is_segmentby_column) == list_length(decompression_map)); - const bool is_segmentby = list_nth_int(is_segmentby_column, compressed_column_index); - if (out_is_segmentby) + int maxattno = 0; + for (int compressed_column_index = 0; compressed_column_index < list_length(decompression_map); + compressed_column_index++) { - *out_is_segmentby = is_segmentby; + const int custom_scan_attno = list_nth_int(decompression_map, compressed_column_index); + if (custom_scan_attno <= 0) + { + continue; + } + + const int uncompressed_chunk_attno = + custom_scan_to_uncompressed_chunk_attno(custom->custom_scan_tlist, custom_scan_attno); + + if (uncompressed_chunk_attno > maxattno) + { + maxattno = uncompressed_chunk_attno; + } } - /* - * We support vectorized aggregation either for segmentby columns or for - * columns with bulk decompression enabled. - */ - if (!is_segmentby && - !(bulk_decompression_enabled_for_column && bulk_decompression_enabled_globally)) + vqi.vector_attrs = (bool *) palloc0(sizeof(bool) * (maxattno + 1)); + + for (int compressed_column_index = 0; compressed_column_index < list_length(decompression_map); + compressed_column_index++) { - /* Vectorized aggregation not possible for this particular column. */ - return false; + const int custom_scan_attno = list_nth_int(decompression_map, compressed_column_index); + if (custom_scan_attno <= 0) + { + continue; + } + + const int uncompressed_chunk_attno = + custom_scan_to_uncompressed_chunk_attno(custom->custom_scan_tlist, custom_scan_attno); + + vqi.vector_attrs[uncompressed_chunk_attno] = + is_vector_compressed_column(custom, compressed_column_index, NULL); } - return true; + return vqi; } +/* + * Whether we can vectorize this particular aggregate. + */ static bool -can_vectorize_aggref(Aggref *aggref, CustomScan *custom) +can_vectorize_aggref(Aggref *aggref, CustomScan *custom, VectorQualInfo *vqi) { - if (aggref->aggfilter != NULL) - { - /* Filter clause on aggregate is not supported. */ - return false; - } - if (aggref->aggdirectargs != NIL) { /* Can't process ordered-set aggregates with direct arguments. */ @@ -319,8 +391,13 @@ can_vectorize_aggref(Aggref *aggref, CustomScan *custom) if (aggref->aggfilter != NULL) { - /* Can't process aggregates with filter clause. */ - return false; + /* Can process aggregates with filter clause if it's vectorizable. */ + Node *aggfilter_vectorized = vector_qual_make((Node *) aggref->aggfilter, vqi); + if (aggfilter_vectorized == NULL) + { + return false; + } + aggref->aggfilter = (Expr *) aggfilter_vectorized; } if (get_vector_aggregate(aggref->aggfnoid) == NULL) @@ -356,6 +433,9 @@ can_vectorize_aggref(Aggref *aggref, CustomScan *custom) static bool can_vectorize_grouping(Agg *agg, CustomScan *custom, List *resolved_targetlist) { + /* + * We support vectorized aggregation without grouping. + */ if (agg->numCols == 0) { return true; @@ -577,6 +657,12 @@ try_insert_vector_agg_node(Plan *plan) return plan; } + /* + * Build supplementary info to determine whether we can vectorize the + * aggregate FILTER clauses. + */ + VectorQualInfo vqi = build_aggfilter_vector_qual_info(custom); + /* Now check the output targetlist. */ ListCell *lc; foreach (lc, resolved_targetlist) @@ -585,7 +671,7 @@ try_insert_vector_agg_node(Plan *plan) if (IsA(target_entry->expr, Aggref)) { Aggref *aggref = castNode(Aggref, target_entry->expr); - if (!can_vectorize_aggref(aggref, custom)) + if (!can_vectorize_aggref(aggref, custom, &vqi)) { /* Aggregate function not vectorizable. */ return plan; diff --git a/tsl/test/expected/vector_agg_filter.out b/tsl/test/expected/vector_agg_filter.out new file mode 100644 index 00000000000..13629d3e4b3 --- /dev/null +++ b/tsl/test/expected/vector_agg_filter.out @@ -0,0 +1,2965 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +-- helper function: float -> pseudorandom float [-0.5..0.5] +CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ + SELECT hashfloat8(x::float8) / pow(2, 32) +$$ LANGUAGE SQL; +-- non-vectorizable equality operator +create operator === (function = 'int4eq', rightarg = int4, leftarg = int4); +-- an abs() function that is stable not immutable +create function stable_abs(x int4) returns int4 as 'int4abs' language internal stable; +\set CHUNKS 2::int +\set CHUNK_ROWS 100000::int +\set GROUPING_CARDINALITY 10::int +create table aggfilter(t int, s int, + cint2 int2, dropped int4, cint4 int4); +select create_hypertable('aggfilter', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); +NOTICE: adding not-null constraint to column "s" + create_hypertable +------------------------ + (1,public,aggfilter,t) +(1 row) + +create view source as +select s * 10000 + t as t, + s, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + 1 as dropped, + (mix(s + t * 1021) * 32767)::int4 as cint4 +from + generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, + generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) +; +insert into aggfilter select * from source where s = 1; +alter table aggfilter set (timescaledb.compress, timescaledb.compress_orderby = 't', + timescaledb.compress_segmentby = 's'); +select count(compress_chunk(x)) from show_chunks('aggfilter') x; + count +------- + 1 +(1 row) + +alter table aggfilter add column ss int default 11; +alter table aggfilter drop column dropped; +insert into aggfilter +select t, s, cint2, cint4, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss +from source where s != 1 +; +select count(compress_chunk(x)) from show_chunks('aggfilter') x; + count +------- + 2 +(1 row) + +vacuum freeze analyze aggfilter; +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +select + format('%sselect %s%s(%s)%s from aggfilter%s%s%s;', + explain, + grouping || ', ', + function, variable, + ' filter (where ' || agg_filter || ')', + ' where ' || condition, + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) +from + unnest(array[ + 'explain (costs off) ', + null]) explain, + unnest(array[ + 's', + 'ss', + 'cint2', + 'cint4', + '*']) variable, + unnest(array[ + 'min', + 'count']) function, + unnest(array[ + null, + 'cint2 > 0', + 'cint2 is null']) with ordinality as condition(condition, n), + unnest(array[ + null, + 's']) with ordinality as grouping(grouping, n), + unnest(array[ + null, + 'cint2 < 0', + 'ss > 1000', + 'cint4 > 0', + 's != 5']) with ordinality as agg_filter(agg_filter, n) +where + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') +order by explain, condition.n, variable, function, grouping.n, agg_filter.n +\gexec +select count(*) from aggfilter; + count +-------- + 200000 +(1 row) + +select count(*) filter (where cint2 < 0) from aggfilter; + count +-------- + 100139 +(1 row) + +select count(*) filter (where ss > 1000) from aggfilter; + count +------- + 0 +(1 row) + +select count(*) filter (where cint4 > 0) from aggfilter; + count +-------- + 100038 +(1 row) + +select count(*) filter (where s != 5) from aggfilter; + count +-------- + 180000 +(1 row) + +select s, count(*) from aggfilter group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select s, count(*) filter (where cint2 < 0) from aggfilter group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 9968 + 1 | 9885 + 2 | 10113 + 3 | 10088 + 4 | 10074 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 +(10 rows) + +select s, count(*) filter (where ss > 1000) from aggfilter group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(*) filter (where cint4 > 0) from aggfilter group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 10002 + 1 | 10046 + 2 | 9885 + 3 | 10063 + 4 | 9995 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 +(10 rows) + +select s, count(*) filter (where s != 5) from aggfilter group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select count(cint2) from aggfilter; + count +-------- + 199810 +(1 row) + +select count(cint2) filter (where cint2 < 0) from aggfilter; + count +-------- + 100139 +(1 row) + +select count(cint2) filter (where ss > 1000) from aggfilter; + count +------- + 0 +(1 row) + +select count(cint2) filter (where cint4 > 0) from aggfilter; + count +------- + 99946 +(1 row) + +select count(cint2) filter (where s != 5) from aggfilter; + count +-------- + 179829 +(1 row) + +select s, count(cint2) from aggfilter group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 19981 + 1 | 19981 + 2 | 19981 + 3 | 19981 + 4 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 +(10 rows) + +select s, count(cint2) filter (where cint2 < 0) from aggfilter group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 9968 + 1 | 9885 + 2 | 10113 + 3 | 10088 + 4 | 10074 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 +(10 rows) + +select s, count(cint2) filter (where ss > 1000) from aggfilter group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint2) filter (where cint4 > 0) from aggfilter group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 9993 + 1 | 10034 + 2 | 9876 + 3 | 10052 + 4 | 9990 + 5 | 10095 + 6 | 9968 + 7 | 9976 + 8 | 10010 + 9 | 9952 +(10 rows) + +select s, count(cint2) filter (where s != 5) from aggfilter group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 19981 + 1 | 19981 + 2 | 19981 + 3 | 19981 + 4 | 19981 + 5 | 0 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 +(10 rows) + +select min(cint2) from aggfilter; + min +-------- + -16383 +(1 row) + +select min(cint2) filter (where cint2 < 0) from aggfilter; + min +-------- + -16383 +(1 row) + +select min(cint2) filter (where ss > 1000) from aggfilter; + min +----- + +(1 row) + +select min(cint2) filter (where cint4 > 0) from aggfilter; + min +-------- + -16383 +(1 row) + +select min(cint2) filter (where s != 5) from aggfilter; + min +-------- + -16383 +(1 row) + +select s, min(cint2) from aggfilter group by s order by min(cint2), s limit 10; + s | min +---+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 1 | -16378 + 9 | -16375 +(10 rows) + +select s, min(cint2) filter (where cint2 < 0) from aggfilter group by s order by min(cint2), s limit 10; + s | min +---+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 1 | -16378 + 9 | -16375 +(10 rows) + +select s, min(cint2) filter (where ss > 1000) from aggfilter group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 4 | + 5 | + 6 | + 2 | + 7 | + 8 | + 3 | + 1 | + 9 | +(10 rows) + +select s, min(cint2) filter (where cint4 > 0) from aggfilter group by s order by min(cint2), s limit 10; + s | min +---+-------- + 0 | -16380 + 4 | -16381 + 5 | -16383 + 6 | -16379 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16380 + 1 | -16378 + 9 | -16375 +(10 rows) + +select s, min(cint2) filter (where s != 5) from aggfilter group by s order by min(cint2), s limit 10; + s | min +---+-------- + 0 | -16383 + 4 | -16383 + 5 | + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 1 | -16378 + 9 | -16375 +(10 rows) + +select count(cint4) from aggfilter; + count +-------- + 200000 +(1 row) + +select count(cint4) filter (where cint2 < 0) from aggfilter; + count +-------- + 100139 +(1 row) + +select count(cint4) filter (where ss > 1000) from aggfilter; + count +------- + 0 +(1 row) + +select count(cint4) filter (where cint4 > 0) from aggfilter; + count +-------- + 100038 +(1 row) + +select count(cint4) filter (where s != 5) from aggfilter; + count +-------- + 180000 +(1 row) + +select s, count(cint4) from aggfilter group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select s, count(cint4) filter (where cint2 < 0) from aggfilter group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 9968 + 1 | 9885 + 2 | 10113 + 3 | 10088 + 4 | 10074 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 +(10 rows) + +select s, count(cint4) filter (where ss > 1000) from aggfilter group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint4) filter (where cint4 > 0) from aggfilter group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 10002 + 1 | 10046 + 2 | 9885 + 3 | 10063 + 4 | 9995 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 +(10 rows) + +select s, count(cint4) filter (where s != 5) from aggfilter group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select min(cint4) from aggfilter; + min +-------- + -16383 +(1 row) + +select min(cint4) filter (where cint2 < 0) from aggfilter; + min +-------- + -16383 +(1 row) + +select min(cint4) filter (where ss > 1000) from aggfilter; + min +----- + +(1 row) + +select min(cint4) filter (where cint4 > 0) from aggfilter; + min +----- + 1 +(1 row) + +select min(cint4) filter (where s != 5) from aggfilter; + min +-------- + -16383 +(1 row) + +select s, min(cint4) from aggfilter group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 2 | -16383 + 7 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | -16380 +(10 rows) + +select s, min(cint4) filter (where cint2 < 0) from aggfilter group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16382 + 2 | -16383 + 7 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16381 + 8 | -16382 + 9 | -16381 + 5 | -16380 +(10 rows) + +select s, min(cint4) filter (where ss > 1000) from aggfilter group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | + 2 | + 7 | + 1 | + 3 | + 4 | + 6 | + 8 | + 9 | + 5 | +(10 rows) + +select s, min(cint4) filter (where cint4 > 0) from aggfilter group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | 1 + 2 | 2 + 7 | 1 + 1 | 3 + 3 | 2 + 4 | 2 + 6 | 2 + 8 | 2 + 9 | 2 + 5 | 2 +(10 rows) + +select s, min(cint4) filter (where s != 5) from aggfilter group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 2 | -16383 + 7 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | +(10 rows) + +select count(s) from aggfilter; + count +-------- + 200000 +(1 row) + +select count(s) filter (where cint2 < 0) from aggfilter; + count +-------- + 100139 +(1 row) + +select count(s) filter (where ss > 1000) from aggfilter; + count +------- + 0 +(1 row) + +select count(s) filter (where cint4 > 0) from aggfilter; + count +-------- + 100038 +(1 row) + +select count(s) filter (where s != 5) from aggfilter; + count +-------- + 180000 +(1 row) + +select s, count(s) from aggfilter group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select s, count(s) filter (where cint2 < 0) from aggfilter group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 9968 + 1 | 9885 + 2 | 10113 + 3 | 10088 + 4 | 10074 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 +(10 rows) + +select s, count(s) filter (where ss > 1000) from aggfilter group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(s) filter (where cint4 > 0) from aggfilter group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 10002 + 1 | 10046 + 2 | 9885 + 3 | 10063 + 4 | 9995 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 +(10 rows) + +select s, count(s) filter (where s != 5) from aggfilter group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select min(s) from aggfilter; + min +----- + 0 +(1 row) + +select min(s) filter (where cint2 < 0) from aggfilter; + min +----- + 0 +(1 row) + +select min(s) filter (where ss > 1000) from aggfilter; + min +----- + +(1 row) + +select min(s) filter (where cint4 > 0) from aggfilter; + min +----- + 0 +(1 row) + +select min(s) filter (where s != 5) from aggfilter; + min +----- + 0 +(1 row) + +select s, min(s) from aggfilter group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where cint2 < 0) from aggfilter group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where ss > 1000) from aggfilter group by s order by min(s), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(s) filter (where cint4 > 0) from aggfilter group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where s != 5) from aggfilter group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select count(ss) from aggfilter; + count +-------- + 199981 +(1 row) + +select count(ss) filter (where cint2 < 0) from aggfilter; + count +-------- + 100127 +(1 row) + +select count(ss) filter (where ss > 1000) from aggfilter; + count +------- + 0 +(1 row) + +select count(ss) filter (where cint4 > 0) from aggfilter; + count +-------- + 100027 +(1 row) + +select count(ss) filter (where s != 5) from aggfilter; + count +-------- + 179981 +(1 row) + +select s, count(ss) from aggfilter group by s order by count(ss), s limit 10; + s | count +---+------- + 3 | 19981 + 0 | 20000 + 1 | 20000 + 2 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select s, count(ss) filter (where cint2 < 0) from aggfilter group by s order by count(ss), s limit 10; + s | count +---+------- + 3 | 10076 + 0 | 9968 + 1 | 9885 + 2 | 10113 + 4 | 10074 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 +(10 rows) + +select s, count(ss) filter (where ss > 1000) from aggfilter group by s order by count(ss), s limit 10; + s | count +---+------- + 3 | 0 + 0 | 0 + 1 | 0 + 2 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(ss) filter (where cint4 > 0) from aggfilter group by s order by count(ss), s limit 10; + s | count +---+------- + 3 | 10052 + 0 | 10002 + 1 | 10046 + 2 | 9885 + 4 | 9995 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 +(10 rows) + +select s, count(ss) filter (where s != 5) from aggfilter group by s order by count(ss), s limit 10; + s | count +---+------- + 3 | 19981 + 0 | 20000 + 1 | 20000 + 2 | 20000 + 4 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select min(ss) from aggfilter; + min +----- + 0 +(1 row) + +select min(ss) filter (where cint2 < 0) from aggfilter; + min +----- + 0 +(1 row) + +select min(ss) filter (where ss > 1000) from aggfilter; + min +----- + +(1 row) + +select min(ss) filter (where cint4 > 0) from aggfilter; + min +----- + 0 +(1 row) + +select min(ss) filter (where s != 5) from aggfilter; + min +----- + 0 +(1 row) + +select s, min(ss) from aggfilter group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where cint2 < 0) from aggfilter group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where ss > 1000) from aggfilter group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 1 | + 2 | +(10 rows) + +select s, min(ss) filter (where cint4 > 0) from aggfilter group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where s != 5) from aggfilter group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select count(*) from aggfilter where cint2 > 0; + count +------- + 99664 +(1 row) + +select count(*) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(*) filter (where ss > 1000) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(*) filter (where cint4 > 0) from aggfilter where cint2 > 0; + count +------- + 49817 +(1 row) + +select count(*) filter (where s != 5) from aggfilter where cint2 > 0; + count +------- + 89554 +(1 row) + +select s, count(*) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select s, count(*) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(*) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(*) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 4923 + 6 | 4911 + 3 | 4972 + 8 | 4929 + 4 | 4944 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 1 | 5067 + 5 | 5167 +(10 rows) + +select s, count(*) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 0 +(10 rows) + +select count(cint2) from aggfilter where cint2 > 0; + count +------- + 99664 +(1 row) + +select count(cint2) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(cint2) filter (where ss > 1000) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0; + count +------- + 49817 +(1 row) + +select count(cint2) filter (where s != 5) from aggfilter where cint2 > 0; + count +------- + 89554 +(1 row) + +select s, count(cint2) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select s, count(cint2) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(cint2) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 4923 + 6 | 4911 + 3 | 4972 + 8 | 4929 + 4 | 4944 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 1 | 5067 + 5 | 5167 +(10 rows) + +select s, count(cint2) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 0 +(10 rows) + +select min(cint2) from aggfilter where cint2 > 0; + min +----- + 1 +(1 row) + +select min(cint2) filter (where cint2 < 0) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(cint2) filter (where ss > 1000) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0; + min +----- + 1 +(1 row) + +select min(cint2) filter (where s != 5) from aggfilter where cint2 > 0; + min +----- + 1 +(1 row) + +select s, min(cint2) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | 1 + 2 | 1 + 3 | 1 + 5 | 1 + 7 | 1 + 8 | 1 + 9 | 2 + 6 | 3 + 0 | 4 + 4 | 4 +(10 rows) + +select s, min(cint2) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | + 2 | + 3 | + 5 | + 7 | + 8 | + 9 | + 6 | + 0 | + 4 | +(10 rows) + +select s, min(cint2) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | + 2 | + 3 | + 5 | + 7 | + 8 | + 9 | + 6 | + 0 | + 4 | +(10 rows) + +select s, min(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | 4 + 2 | 4 + 3 | 1 + 5 | 1 + 7 | 1 + 8 | 1 + 9 | 6 + 6 | 3 + 0 | 6 + 4 | 4 +(10 rows) + +select s, min(cint2) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | 1 + 2 | 1 + 3 | 1 + 5 | + 7 | 1 + 8 | 1 + 9 | 2 + 6 | 3 + 0 | 4 + 4 | 4 +(10 rows) + +select count(cint4) from aggfilter where cint2 > 0; + count +------- + 99664 +(1 row) + +select count(cint4) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(cint4) filter (where ss > 1000) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0; + count +------- + 49817 +(1 row) + +select count(cint4) filter (where s != 5) from aggfilter where cint2 > 0; + count +------- + 89554 +(1 row) + +select s, count(cint4) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select s, count(cint4) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(cint4) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; + s | count +---+------- + 2 | 4923 + 6 | 4911 + 3 | 4972 + 8 | 4929 + 4 | 4944 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 1 | 5067 + 5 | 5167 +(10 rows) + +select s, count(cint4) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 0 +(10 rows) + +select min(cint4) from aggfilter where cint2 > 0; + min +-------- + -16383 +(1 row) + +select min(cint4) filter (where cint2 < 0) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(cint4) filter (where ss > 1000) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0; + min +----- + 1 +(1 row) + +select min(cint4) filter (where s != 5) from aggfilter where cint2 > 0; + min +-------- + -16383 +(1 row) + +select s, min(cint4) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 7 | -16382 + 9 | -16382 + 2 | -16377 + 8 | -16377 + 5 | -16375 +(10 rows) + +select s, min(cint4) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | + 1 | + 3 | + 4 | + 6 | + 7 | + 9 | + 2 | + 8 | + 5 | +(10 rows) + +select s, min(cint4) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | + 1 | + 3 | + 4 | + 6 | + 7 | + 9 | + 2 | + 8 | + 5 | +(10 rows) + +select s, min(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | 1 + 1 | 7 + 3 | 2 + 4 | 5 + 6 | 2 + 7 | 1 + 9 | 2 + 2 | 2 + 8 | 5 + 5 | 2 +(10 rows) + +select s, min(cint4) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 7 | -16382 + 9 | -16382 + 2 | -16377 + 8 | -16377 + 5 | +(10 rows) + +select count(s) from aggfilter where cint2 > 0; + count +------- + 99664 +(1 row) + +select count(s) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(s) filter (where ss > 1000) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(s) filter (where cint4 > 0) from aggfilter where cint2 > 0; + count +------- + 49817 +(1 row) + +select count(s) filter (where s != 5) from aggfilter where cint2 > 0; + count +------- + 89554 +(1 row) + +select s, count(s) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select s, count(s) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(s) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(s) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; + s | count +---+------- + 2 | 4923 + 6 | 4911 + 3 | 4972 + 8 | 4929 + 4 | 4944 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 1 | 5067 + 5 | 5167 +(10 rows) + +select s, count(s) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 0 +(10 rows) + +select min(s) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select min(s) filter (where cint2 < 0) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(s) filter (where ss > 1000) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(s) filter (where cint4 > 0) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select min(s) filter (where s != 5) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select s, min(s) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(s) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(s) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select count(ss) from aggfilter where cint2 > 0; + count +------- + 99657 +(1 row) + +select count(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(ss) filter (where ss > 1000) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0; + count +------- + 49813 +(1 row) + +select count(ss) filter (where s != 5) from aggfilter where cint2 > 0; + count +------- + 89547 +(1 row) + +select s, count(ss) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; + s | count +---+------- + 2 | 9868 + 3 | 9886 + 6 | 9890 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select s, count(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; + s | count +---+------- + 2 | 0 + 3 | 0 + 6 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(ss) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; + s | count +---+------- + 2 | 0 + 3 | 0 + 6 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; + s | count +---+------- + 2 | 4923 + 3 | 4968 + 6 | 4911 + 8 | 4929 + 4 | 4944 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 1 | 5067 + 5 | 5167 +(10 rows) + +select s, count(ss) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; + s | count +---+------- + 2 | 9868 + 3 | 9886 + 6 | 9890 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 0 +(10 rows) + +select min(ss) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select min(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(ss) filter (where ss > 1000) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select min(ss) filter (where s != 5) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select s, min(ss) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 1 | + 2 | +(10 rows) + +select s, min(ss) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 1 | + 2 | +(10 rows) + +select s, min(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select count(*) from aggfilter where cint2 is null; + count +------- + 190 +(1 row) + +select count(*) filter (where cint2 < 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(*) filter (where ss > 1000) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(*) filter (where cint4 > 0) from aggfilter where cint2 is null; + count +------- + 92 +(1 row) + +select count(*) filter (where s != 5) from aggfilter where cint2 is null; + count +------- + 171 +(1 row) + +select s, count(*) from aggfilter where cint2 is null group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select s, count(*) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(*) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(*) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 9 + 1 | 12 + 2 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 +(10 rows) + +select s, count(*) filter (where s != 5) from aggfilter where cint2 is null group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select count(cint2) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint2) filter (where cint2 < 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint2) filter (where ss > 1000) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint2) filter (where s != 5) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select s, count(cint2) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint2) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint2) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint2) filter (where s != 5) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select min(cint2) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint2) filter (where cint2 < 0) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint2) filter (where ss > 1000) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint2) filter (where s != 5) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select s, min(cint2) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(cint2) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(cint2) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(cint2) filter (where s != 5) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select count(cint4) from aggfilter where cint2 is null; + count +------- + 190 +(1 row) + +select count(cint4) filter (where cint2 < 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint4) filter (where ss > 1000) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null; + count +------- + 92 +(1 row) + +select count(cint4) filter (where s != 5) from aggfilter where cint2 is null; + count +------- + 171 +(1 row) + +select s, count(cint4) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select s, count(cint4) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint4) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 9 + 1 | 12 + 2 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 +(10 rows) + +select s, count(cint4) filter (where s != 5) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select min(cint4) from aggfilter where cint2 is null; + min +-------- + -16291 +(1 row) + +select min(cint4) filter (where cint2 < 0) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint4) filter (where ss > 1000) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null; + min +----- + 473 +(1 row) + +select min(cint4) filter (where s != 5) from aggfilter where cint2 is null; + min +-------- + -16291 +(1 row) + +select s, min(cint4) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16291 + 7 | -16091 + 4 | -15724 + 5 | -15279 + 2 | -15063 + 6 | -14998 + 9 | -14699 + 8 | -14214 + 1 | -12217 + 3 | -9908 +(10 rows) + +select s, min(cint4) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | + 7 | + 4 | + 5 | + 2 | + 6 | + 9 | + 8 | + 1 | + 3 | +(10 rows) + +select s, min(cint4) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | + 7 | + 4 | + 5 | + 2 | + 6 | + 9 | + 8 | + 1 | + 3 | +(10 rows) + +select s, min(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; + s | min +---+------ + 0 | 701 + 7 | 1695 + 4 | 1821 + 5 | 587 + 2 | 2876 + 6 | 1003 + 9 | 2489 + 8 | 1334 + 1 | 2034 + 3 | 473 +(10 rows) + +select s, min(cint4) filter (where s != 5) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16291 + 7 | -16091 + 4 | -15724 + 5 | + 2 | -15063 + 6 | -14998 + 9 | -14699 + 8 | -14214 + 1 | -12217 + 3 | -9908 +(10 rows) + +select count(s) from aggfilter where cint2 is null; + count +------- + 190 +(1 row) + +select count(s) filter (where cint2 < 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(s) filter (where ss > 1000) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(s) filter (where cint4 > 0) from aggfilter where cint2 is null; + count +------- + 92 +(1 row) + +select count(s) filter (where s != 5) from aggfilter where cint2 is null; + count +------- + 171 +(1 row) + +select s, count(s) from aggfilter where cint2 is null group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select s, count(s) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(s) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(s) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 9 + 1 | 12 + 2 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 +(10 rows) + +select s, count(s) filter (where s != 5) from aggfilter where cint2 is null group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select min(s) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select min(s) filter (where cint2 < 0) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(s) filter (where ss > 1000) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(s) filter (where cint4 > 0) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select min(s) filter (where s != 5) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select s, min(s) from aggfilter where cint2 is null group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by min(s), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(s) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by min(s), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(s) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where s != 5) from aggfilter where cint2 is null group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select count(ss) from aggfilter where cint2 is null; + count +------- + 190 +(1 row) + +select count(ss) filter (where cint2 < 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(ss) filter (where ss > 1000) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(ss) filter (where cint4 > 0) from aggfilter where cint2 is null; + count +------- + 92 +(1 row) + +select count(ss) filter (where s != 5) from aggfilter where cint2 is null; + count +------- + 171 +(1 row) + +select s, count(ss) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select s, count(ss) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(ss) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(ss) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; + s | count +---+------- + 0 | 9 + 1 | 12 + 2 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 +(10 rows) + +select s, count(ss) filter (where s != 5) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select min(ss) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select min(ss) filter (where cint2 < 0) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(ss) filter (where ss > 1000) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(ss) filter (where cint4 > 0) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select min(ss) filter (where s != 5) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select s, min(ss) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 1 | + 2 | +(10 rows) + +select s, min(ss) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 1 | + 2 | +(10 rows) + +select s, min(ss) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where s != 5) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +reset timescaledb.debug_require_vector_agg; +-- FILTER that is not vectorizable +set timescaledb.debug_require_vector_agg = 'forbid'; +select count(*) filter (where cint2 === 0) from aggfilter; + count +------- + 7 +(1 row) + +-- FILTER with stable function +set timescaledb.debug_require_vector_agg = 'require'; +select count(*) filter (where cint2 = stable_abs(0)) from aggfilter; + count +------- + 7 +(1 row) + +reset timescaledb.debug_require_vector_agg; diff --git a/tsl/test/expected/vectorized_aggregation.out b/tsl/test/expected/vectorized_aggregation.out index 8887dac8469..01f690b743a 100644 --- a/tsl/test/expected/vectorized_aggregation.out +++ b/tsl/test/expected/vectorized_aggregation.out @@ -180,7 +180,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0; Filter: (_hyper_1_10_chunk.segment_by_value > 0) (65 rows) --- Vectorization not possible due to a used filter +-- Vectorization with filter on compressed columns :EXPLAIN SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0 AND int_value > 0; QUERY PLAN @@ -2858,7 +2858,7 @@ SELECT sum(int_value) FROM testtable; 3538 (1 row) --- Aggregation filters are not supported at the moment +-- Vectorizable aggregation filters are supported :EXPLAIN SELECT sum(segment_by_value) FILTER (WHERE segment_by_value > 99999) FROM testtable; QUERY PLAN @@ -2869,67 +2869,77 @@ SELECT sum(segment_by_value) FILTER (WHERE segment_by_value > 99999) FROM testta Output: (PARTIAL sum(_hyper_1_81_chunk.segment_by_value) FILTER (WHERE (_hyper_1_81_chunk.segment_by_value > 99999))) Workers Planned: 2 -> Parallel Append - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_81_chunk.segment_by_value) FILTER (WHERE (_hyper_1_81_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_81_chunk.segment_by_value) FILTER (WHERE (_hyper_1_81_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_81_chunk Output: _hyper_1_81_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_91_chunk Output: compress_hyper_2_91_chunk._ts_meta_count, compress_hyper_2_91_chunk.segment_by_value, compress_hyper_2_91_chunk._ts_meta_min_1, compress_hyper_2_91_chunk._ts_meta_max_1, compress_hyper_2_91_chunk."time", compress_hyper_2_91_chunk.int_value, compress_hyper_2_91_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_82_chunk.segment_by_value) FILTER (WHERE (_hyper_1_82_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_82_chunk.segment_by_value) FILTER (WHERE (_hyper_1_82_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_82_chunk Output: _hyper_1_82_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_92_chunk Output: compress_hyper_2_92_chunk._ts_meta_count, compress_hyper_2_92_chunk.segment_by_value, compress_hyper_2_92_chunk._ts_meta_min_1, compress_hyper_2_92_chunk._ts_meta_max_1, compress_hyper_2_92_chunk."time", compress_hyper_2_92_chunk.int_value, compress_hyper_2_92_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_83_chunk.segment_by_value) FILTER (WHERE (_hyper_1_83_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_83_chunk.segment_by_value) FILTER (WHERE (_hyper_1_83_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_83_chunk Output: _hyper_1_83_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_93_chunk Output: compress_hyper_2_93_chunk._ts_meta_count, compress_hyper_2_93_chunk.segment_by_value, compress_hyper_2_93_chunk._ts_meta_min_1, compress_hyper_2_93_chunk._ts_meta_max_1, compress_hyper_2_93_chunk."time", compress_hyper_2_93_chunk.int_value, compress_hyper_2_93_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_84_chunk.segment_by_value) FILTER (WHERE (_hyper_1_84_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_84_chunk.segment_by_value) FILTER (WHERE (_hyper_1_84_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_84_chunk Output: _hyper_1_84_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_94_chunk Output: compress_hyper_2_94_chunk._ts_meta_count, compress_hyper_2_94_chunk.segment_by_value, compress_hyper_2_94_chunk._ts_meta_min_1, compress_hyper_2_94_chunk._ts_meta_max_1, compress_hyper_2_94_chunk."time", compress_hyper_2_94_chunk.int_value, compress_hyper_2_94_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_85_chunk.segment_by_value) FILTER (WHERE (_hyper_1_85_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_85_chunk.segment_by_value) FILTER (WHERE (_hyper_1_85_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_85_chunk Output: _hyper_1_85_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_95_chunk Output: compress_hyper_2_95_chunk._ts_meta_count, compress_hyper_2_95_chunk.segment_by_value, compress_hyper_2_95_chunk._ts_meta_min_1, compress_hyper_2_95_chunk._ts_meta_max_1, compress_hyper_2_95_chunk."time", compress_hyper_2_95_chunk.int_value, compress_hyper_2_95_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_86_chunk.segment_by_value) FILTER (WHERE (_hyper_1_86_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_86_chunk.segment_by_value) FILTER (WHERE (_hyper_1_86_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_86_chunk Output: _hyper_1_86_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_96_chunk Output: compress_hyper_2_96_chunk._ts_meta_count, compress_hyper_2_96_chunk.segment_by_value, compress_hyper_2_96_chunk._ts_meta_min_1, compress_hyper_2_96_chunk._ts_meta_max_1, compress_hyper_2_96_chunk."time", compress_hyper_2_96_chunk.int_value, compress_hyper_2_96_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_87_chunk.segment_by_value) FILTER (WHERE (_hyper_1_87_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_87_chunk.segment_by_value) FILTER (WHERE (_hyper_1_87_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_87_chunk Output: _hyper_1_87_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_97_chunk Output: compress_hyper_2_97_chunk._ts_meta_count, compress_hyper_2_97_chunk.segment_by_value, compress_hyper_2_97_chunk._ts_meta_min_1, compress_hyper_2_97_chunk._ts_meta_max_1, compress_hyper_2_97_chunk."time", compress_hyper_2_97_chunk.int_value, compress_hyper_2_97_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_88_chunk.segment_by_value) FILTER (WHERE (_hyper_1_88_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_88_chunk.segment_by_value) FILTER (WHERE (_hyper_1_88_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_88_chunk Output: _hyper_1_88_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_98_chunk Output: compress_hyper_2_98_chunk._ts_meta_count, compress_hyper_2_98_chunk.segment_by_value, compress_hyper_2_98_chunk._ts_meta_min_1, compress_hyper_2_98_chunk._ts_meta_max_1, compress_hyper_2_98_chunk."time", compress_hyper_2_98_chunk.int_value, compress_hyper_2_98_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_89_chunk.segment_by_value) FILTER (WHERE (_hyper_1_89_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_89_chunk.segment_by_value) FILTER (WHERE (_hyper_1_89_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_89_chunk Output: _hyper_1_89_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_99_chunk Output: compress_hyper_2_99_chunk._ts_meta_count, compress_hyper_2_99_chunk.segment_by_value, compress_hyper_2_99_chunk._ts_meta_min_1, compress_hyper_2_99_chunk._ts_meta_max_1, compress_hyper_2_99_chunk."time", compress_hyper_2_99_chunk.int_value, compress_hyper_2_99_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_90_chunk.segment_by_value) FILTER (WHERE (_hyper_1_90_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_90_chunk.segment_by_value) FILTER (WHERE (_hyper_1_90_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_90_chunk Output: _hyper_1_90_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_100_chunk Output: compress_hyper_2_100_chunk._ts_meta_count, compress_hyper_2_100_chunk.segment_by_value, compress_hyper_2_100_chunk._ts_meta_min_1, compress_hyper_2_100_chunk._ts_meta_max_1, compress_hyper_2_100_chunk."time", compress_hyper_2_100_chunk.int_value, compress_hyper_2_100_chunk.float_value -(66 rows) +(76 rows) SET timescaledb.enable_vectorized_aggregation = OFF; SELECT sum(segment_by_value) FILTER (WHERE segment_by_value > 99999) FROM testtable; diff --git a/tsl/test/sql/CMakeLists.txt b/tsl/test/sql/CMakeLists.txt index 041f9300c10..af050f455cf 100644 --- a/tsl/test/sql/CMakeLists.txt +++ b/tsl/test/sql/CMakeLists.txt @@ -115,6 +115,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) recompress_chunk_segmentwise.sql feature_flags.sql vector_agg_default.sql + vector_agg_filter.sql vector_agg_memory.sql vector_agg_segmentby.sql) diff --git a/tsl/test/sql/vector_agg_filter.sql b/tsl/test/sql/vector_agg_filter.sql new file mode 100644 index 00000000000..d3423d84eac --- /dev/null +++ b/tsl/test/sql/vector_agg_filter.sql @@ -0,0 +1,121 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. + +\c :TEST_DBNAME :ROLE_SUPERUSER +-- helper function: float -> pseudorandom float [-0.5..0.5] +CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ + SELECT hashfloat8(x::float8) / pow(2, 32) +$$ LANGUAGE SQL; +-- non-vectorizable equality operator +create operator === (function = 'int4eq', rightarg = int4, leftarg = int4); +-- an abs() function that is stable not immutable +create function stable_abs(x int4) returns int4 as 'int4abs' language internal stable; + +\set CHUNKS 2::int +\set CHUNK_ROWS 100000::int +\set GROUPING_CARDINALITY 10::int + +create table aggfilter(t int, s int, + cint2 int2, dropped int4, cint4 int4); +select create_hypertable('aggfilter', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); + +create view source as +select s * 10000 + t as t, + s, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + 1 as dropped, + (mix(s + t * 1021) * 32767)::int4 as cint4 +from + generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, + generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) +; + +insert into aggfilter select * from source where s = 1; + +alter table aggfilter set (timescaledb.compress, timescaledb.compress_orderby = 't', + timescaledb.compress_segmentby = 's'); + +select count(compress_chunk(x)) from show_chunks('aggfilter') x; + +alter table aggfilter add column ss int default 11; +alter table aggfilter drop column dropped; + +insert into aggfilter +select t, s, cint2, cint4, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss +from source where s != 1 +; +select count(compress_chunk(x)) from show_chunks('aggfilter') x; +vacuum freeze analyze aggfilter; + + + +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; + +select + format('%sselect %s%s(%s)%s from aggfilter%s%s%s;', + explain, + grouping || ', ', + function, variable, + ' filter (where ' || agg_filter || ')', + ' where ' || condition, + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) +from + unnest(array[ + 'explain (costs off) ', + null]) explain, + unnest(array[ + 's', + 'ss', + 'cint2', + 'cint4', + '*']) variable, + unnest(array[ + 'min', + 'count']) function, + unnest(array[ + null, + 'cint2 > 0', + 'cint2 is null']) with ordinality as condition(condition, n), + unnest(array[ + null, + 's']) with ordinality as grouping(grouping, n), + unnest(array[ + null, + 'cint2 < 0', + 'ss > 1000', + 'cint4 > 0', + 's != 5']) with ordinality as agg_filter(agg_filter, n) +where + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') +order by explain, condition.n, variable, function, grouping.n, agg_filter.n +\gexec + +reset timescaledb.debug_require_vector_agg; + +-- FILTER that is not vectorizable +set timescaledb.debug_require_vector_agg = 'forbid'; +select count(*) filter (where cint2 === 0) from aggfilter; +-- FILTER with stable function +set timescaledb.debug_require_vector_agg = 'require'; +select count(*) filter (where cint2 = stable_abs(0)) from aggfilter; + +reset timescaledb.debug_require_vector_agg; + diff --git a/tsl/test/sql/vectorized_aggregation.sql b/tsl/test/sql/vectorized_aggregation.sql index bafecd6b544..324a96716f5 100644 --- a/tsl/test/sql/vectorized_aggregation.sql +++ b/tsl/test/sql/vectorized_aggregation.sql @@ -42,7 +42,7 @@ SELECT sum(segment_by_value) FROM testtable; :EXPLAIN SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0; --- Vectorization not possible due to a used filter +-- Vectorization with filter on compressed columns :EXPLAIN SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0 AND int_value > 0; @@ -330,7 +330,7 @@ SELECT sum(segment_by_value) FROM testtable; SELECT sum(int_value) FROM testtable; --- Aggregation filters are not supported at the moment +-- Vectorizable aggregation filters are supported :EXPLAIN SELECT sum(segment_by_value) FILTER (WHERE segment_by_value > 99999) FROM testtable;