diff --git a/dbms/src/AggregateFunctions/AggregateFunctionWindowFunnel.h b/dbms/src/AggregateFunctions/AggregateFunctionWindowFunnel.h index b62755ef00c..fe83f5d94b9 100644 --- a/dbms/src/AggregateFunctions/AggregateFunctionWindowFunnel.h +++ b/dbms/src/AggregateFunctions/AggregateFunctionWindowFunnel.h @@ -66,7 +66,7 @@ struct AggregateFunctionWindowFunnelData /// either sort whole container or do so partially merging ranges afterwards if (!sorted && !other.sorted) - std::sort(std::begin(events_list), std::end(events_list), Comparator{}); + std::stable_sort(std::begin(events_list), std::end(events_list), Comparator{}); else { const auto begin = std::begin(events_list); @@ -74,10 +74,10 @@ struct AggregateFunctionWindowFunnelData const auto end = std::end(events_list); if (!sorted) - std::sort(begin, middle, Comparator{}); + std::stable_sort(begin, middle, Comparator{}); if (!other.sorted) - std::sort(middle, end, Comparator{}); + std::stable_sort(middle, end, Comparator{}); std::inplace_merge(begin, middle, end, Comparator{}); } @@ -89,7 +89,7 @@ struct AggregateFunctionWindowFunnelData { if (!sorted) { - std::sort(std::begin(events_list), std::end(events_list), Comparator{}); + std::stable_sort(std::begin(events_list), std::end(events_list), Comparator{}); sorted = true; } } @@ -215,19 +215,13 @@ public: void add(AggregateDataPtr place, const IColumn ** columns, const size_t row_num, Arena *) const override { - UInt8 event_level = 0; - for (const auto i : ext::range(1, events_size + 1)) + const auto timestamp = static_cast *>(columns[0])->getData()[row_num]; + // reverse iteration and stable sorting are needed for events that are qualified by more than one condition. + for (auto i = events_size; i > 0; --i) { auto event = static_cast *>(columns[i])->getData()[row_num]; if (event) - { - event_level = i; - break; - } - } - if (event_level) - { - this->data(place).add(static_cast *>(columns[0])->getData()[row_num], event_level); + this->data(place).add(timestamp, i); } } diff --git a/dbms/tests/queries/0_stateless/00632_aggregation_window_funnel.reference b/dbms/tests/queries/0_stateless/00632_aggregation_window_funnel.reference index 4dff9ef38ef..71c9a23879f 100644 --- a/dbms/tests/queries/0_stateless/00632_aggregation_window_funnel.reference +++ b/dbms/tests/queries/0_stateless/00632_aggregation_window_funnel.reference @@ -10,3 +10,4 @@ 1 1 1 +1 diff --git a/dbms/tests/queries/0_stateless/00632_aggregation_window_funnel.sql b/dbms/tests/queries/0_stateless/00632_aggregation_window_funnel.sql index e985956d272..0b1f9855eac 100644 --- a/dbms/tests/queries/0_stateless/00632_aggregation_window_funnel.sql +++ b/dbms/tests/queries/0_stateless/00632_aggregation_window_funnel.sql @@ -25,6 +25,7 @@ select 5 = windowFunnel(4)(timestamp, event = 1003, event = 1004, event = 1005, select 2 = windowFunnel(10000)(timestamp, event = 1001, event = 1008) from funnel_test2; select 1 = windowFunnel(10000)(timestamp, event = 1008, event = 1001) from funnel_test2; select 5 = windowFunnel(4)(timestamp, event = 1003, event = 1004, event = 1005, event = 1006, event = 1007) from funnel_test2; +select 4 = windowFunnel(4)(timestamp, event <= 1007, event >= 1002, event <= 1006, event >= 1004) from funnel_test2; drop table funnel_test; drop table funnel_test2;