diff --git a/docs/en/operations/settings/settings.md b/docs/en/operations/settings/settings.md index ae0d2eeb595..5a0263a1247 100644 --- a/docs/en/operations/settings/settings.md +++ b/docs/en/operations/settings/settings.md @@ -3095,14 +3095,14 @@ Exception: Total regexp lengths too large. ## enable_positional_arguments {#enable-positional-arguments} -Enables or disables supporting positional arguments for [GROUP BY](../../sql-reference/statements/select/group-by.md), [LIMIT BY](../../sql-reference/statements/select/limit-by.md), [ORDER BY](../../sql-reference/statements/select/order-by.md) statements. When you want to use column numbers instead of column names in these clauses, set `enable_positional_arguments = 1`. +Enables or disables supporting positional arguments for [GROUP BY](../../sql-reference/statements/select/group-by.md), [LIMIT BY](../../sql-reference/statements/select/limit-by.md), [ORDER BY](../../sql-reference/statements/select/order-by.md) statements. Possible values: - 0 — Positional arguments aren't supported. - 1 — Positional arguments are supported: column numbers can use instead of column names. -Default value: `0`. +Default value: `1`. **Example** @@ -3113,8 +3113,6 @@ CREATE TABLE positional_arguments(one Int, two Int, three Int) ENGINE=Memory(); INSERT INTO positional_arguments VALUES (10, 20, 30), (20, 20, 10), (30, 10, 20); -SET enable_positional_arguments = 1; - SELECT * FROM positional_arguments ORDER BY 2,3; ``` diff --git a/docs/en/sql-reference/functions/array-functions.md b/docs/en/sql-reference/functions/array-functions.md index 50a394e45fd..e76317b9e47 100644 --- a/docs/en/sql-reference/functions/array-functions.md +++ b/docs/en/sql-reference/functions/array-functions.md @@ -162,6 +162,10 @@ Creates an array from the function arguments. The arguments must be constants and have types that have the smallest common type. At least one argument must be passed, because otherwise it isn’t clear which type of array to create. That is, you can’t use this function to create an empty array (to do that, use the ‘emptyArray\*’ function described above). Returns an ‘Array(T)’ type result, where ‘T’ is the smallest common type out of the passed arguments. +## arrayWithConstant(length, elem) + +Creates an array of length `length` filled with the constant `elem`. + ## arrayConcat Combines arrays passed as arguments. diff --git a/docs/ru/operations/settings/settings.md b/docs/ru/operations/settings/settings.md index 5ad6e4ef3b6..abaa05639c6 100644 --- a/docs/ru/operations/settings/settings.md +++ b/docs/ru/operations/settings/settings.md @@ -3790,14 +3790,14 @@ Exception: Total regexp lengths too large. ## enable_positional_arguments {#enable-positional-arguments} -Включает и отключает поддержку позиционных аргументов для [GROUP BY](../../sql-reference/statements/select/group-by.md), [LIMIT BY](../../sql-reference/statements/select/limit-by.md), [ORDER BY](../../sql-reference/statements/select/order-by.md). Если вы хотите использовать номера столбцов вместо названий в выражениях этих операторов, установите `enable_positional_arguments = 1`. +Включает и отключает поддержку позиционных аргументов для [GROUP BY](../../sql-reference/statements/select/group-by.md), [LIMIT BY](../../sql-reference/statements/select/limit-by.md), [ORDER BY](../../sql-reference/statements/select/order-by.md). Возможные значения: - 0 — Позиционные аргументы не поддерживаются. - 1 — Позиционные аргументы поддерживаются: можно использовать номера столбцов вместо названий столбцов. -Значение по умолчанию: `0`. +Значение по умолчанию: `1`. **Пример** @@ -3808,8 +3808,6 @@ CREATE TABLE positional_arguments(one Int, two Int, three Int) ENGINE=Memory(); INSERT INTO positional_arguments VALUES (10, 20, 30), (20, 20, 10), (30, 10, 20); -SET enable_positional_arguments = 1; - SELECT * FROM positional_arguments ORDER BY 2,3; ``` diff --git a/src/Processors/Transforms/WindowTransform.cpp b/src/Processors/Transforms/WindowTransform.cpp index 5e0d896599c..4155ab7c7f1 100644 --- a/src/Processors/Transforms/WindowTransform.cpp +++ b/src/Processors/Transforms/WindowTransform.cpp @@ -968,9 +968,6 @@ void WindowTransform::updateAggregationState() } } } - - prev_frame_start = frame_start; - prev_frame_end = frame_end; } void WindowTransform::writeOutCurrentRow() @@ -1212,6 +1209,9 @@ void WindowTransform::appendChunk(Chunk & chunk) return; } + prev_frame_start = frame_start; + prev_frame_end = frame_end; + // Move to the next row. The frame will have to be recalculated. // The peer group start is updated at the beginning of the loop, // because current_row might now be past-the-end. @@ -1617,16 +1617,12 @@ struct StatefulWindowFunction : public WindowFunction struct ExponentialTimeDecayedSumState { - RowNumber previous_frame_start; - RowNumber previous_frame_end; Float64 previous_time; Float64 previous_sum; }; struct ExponentialTimeDecayedAvgState { - RowNumber previous_frame_start; - RowNumber previous_frame_end; Float64 previous_time; Float64 previous_sum; Float64 previous_count; @@ -1685,40 +1681,43 @@ struct WindowFunctionExponentialTimeDecayedSum final : public StatefulWindowFunc auto & state = getState(workspace); Float64 result = 0; - Float64 curr_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, transform->current_row); - if (state.previous_frame_start <= transform->frame_start - && transform->frame_start < state.previous_frame_end - && state.previous_frame_end <= transform->frame_end) + if (transform->frame_start < transform->frame_end) { - for (RowNumber i = state.previous_frame_start; i < transform->frame_start; transform->advanceRowNumber(i)) - { - Float64 prev_val = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_VALUE, i); - Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); - result -= std::exp((prev_t - curr_t) / decay_length) * prev_val; - } - result += std::exp((state.previous_time - curr_t) / decay_length) * state.previous_sum; - for (RowNumber i = state.previous_frame_end; i < transform->frame_end; transform->advanceRowNumber(i)) - { - Float64 prev_val = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_VALUE, i); - Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); - result += std::exp((prev_t - curr_t) / decay_length) * prev_val; - } - } - else - { - for (RowNumber i = transform->frame_start; i < transform->frame_end; transform->advanceRowNumber(i)) - { - Float64 prev_val = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_VALUE, i); - Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); - result += std::exp((prev_t - curr_t) / decay_length) * prev_val; - } - } + RowNumber frame_back = transform->prevRowNumber(transform->frame_end); + Float64 back_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, frame_back); - state.previous_sum = result; - state.previous_time = curr_t; - state.previous_frame_start = transform->frame_start; - state.previous_frame_end = transform->frame_end; + if (transform->prev_frame_start <= transform->frame_start + && transform->frame_start < transform->prev_frame_end + && transform->prev_frame_end <= transform->frame_end) + { + for (RowNumber i = transform->prev_frame_start; i < transform->frame_start; transform->advanceRowNumber(i)) + { + Float64 prev_val = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_VALUE, i); + Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); + result -= std::exp((prev_t - back_t) / decay_length) * prev_val; + } + result += std::exp((state.previous_time - back_t) / decay_length) * state.previous_sum; + for (RowNumber i = transform->prev_frame_end; i < transform->frame_end; transform->advanceRowNumber(i)) + { + Float64 prev_val = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_VALUE, i); + Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); + result += std::exp((prev_t - back_t) / decay_length) * prev_val; + } + } + else + { + for (RowNumber i = transform->frame_start; i < transform->frame_end; transform->advanceRowNumber(i)) + { + Float64 prev_val = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_VALUE, i); + Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); + result += std::exp((prev_t - back_t) / decay_length) * prev_val; + } + } + + state.previous_sum = result; + state.previous_time = back_t; + } WindowFunctionHelpers::setValueToOutputColumn(transform, function_index, result); } @@ -1776,18 +1775,24 @@ struct WindowFunctionExponentialTimeDecayedMax final : public WindowFunction void windowInsertResultInto(const WindowTransform * transform, size_t function_index) override { - Float64 result = std::numeric_limits::lowest(); - Float64 curr_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, transform->current_row); + Float64 result = std::numeric_limits::quiet_NaN(); - for (RowNumber i = transform->frame_start; i < transform->frame_end; transform->advanceRowNumber(i)) + if (transform->frame_start < transform->frame_end) { - Float64 value = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_VALUE, i); - Float64 t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); + result = std::numeric_limits::lowest(); + RowNumber frame_back = transform->prevRowNumber(transform->frame_end); + Float64 back_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, frame_back); - /// Avoiding extra calls to `exp` and multiplications. - if (value > result || t > curr_t || result < 0) + for (RowNumber i = transform->frame_start; i < transform->frame_end; transform->advanceRowNumber(i)) { - result = std::max(std::exp((t - curr_t) / decay_length) * value, result); + Float64 value = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_VALUE, i); + Float64 t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); + + /// Avoiding extra calls to `exp` and multiplications. + if (value > result || t > back_t || result < 0) + { + result = std::max(std::exp((t - back_t) / decay_length) * value, result); + } } } @@ -1842,37 +1847,40 @@ struct WindowFunctionExponentialTimeDecayedCount final : public StatefulWindowFu auto & state = getState(workspace); Float64 result = 0; - Float64 curr_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, transform->current_row); - if (state.previous_frame_start <= transform->frame_start - && transform->frame_start < state.previous_frame_end - && state.previous_frame_end <= transform->frame_end) + if (transform->frame_start < transform->frame_end) { - for (RowNumber i = state.previous_frame_start; i < transform->frame_start; transform->advanceRowNumber(i)) - { - Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); - result -= std::exp((prev_t - curr_t) / decay_length); - } - result += std::exp((state.previous_time - curr_t) / decay_length) * state.previous_sum; - for (RowNumber i = state.previous_frame_end; i < transform->frame_end; transform->advanceRowNumber(i)) - { - Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); - result += std::exp((prev_t - curr_t) / decay_length); - } - } - else - { - for (RowNumber i = transform->frame_start; i < transform->frame_end; transform->advanceRowNumber(i)) - { - Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); - result += std::exp((prev_t - curr_t) / decay_length); - } - } + RowNumber frame_back = transform->prevRowNumber(transform->frame_end); + Float64 back_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, frame_back); - state.previous_sum = result; - state.previous_time = curr_t; - state.previous_frame_start = transform->frame_start; - state.previous_frame_end = transform->frame_end; + if (transform->prev_frame_start <= transform->frame_start + && transform->frame_start < transform->prev_frame_end + && transform->prev_frame_end <= transform->frame_end) + { + for (RowNumber i = transform->prev_frame_start; i < transform->frame_start; transform->advanceRowNumber(i)) + { + Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); + result -= std::exp((prev_t - back_t) / decay_length); + } + result += std::exp((state.previous_time - back_t) / decay_length) * state.previous_sum; + for (RowNumber i = transform->prev_frame_end; i < transform->frame_end; transform->advanceRowNumber(i)) + { + Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); + result += std::exp((prev_t - back_t) / decay_length); + } + } + else + { + for (RowNumber i = transform->frame_start; i < transform->frame_end; transform->advanceRowNumber(i)) + { + Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); + result += std::exp((prev_t - back_t) / decay_length); + } + } + + state.previous_sum = result; + state.previous_time = back_t; + } WindowFunctionHelpers::setValueToOutputColumn(transform, function_index, result); } @@ -1935,55 +1943,61 @@ struct WindowFunctionExponentialTimeDecayedAvg final : public StatefulWindowFunc Float64 count = 0; Float64 sum = 0; - Float64 curr_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, transform->current_row); + Float64 result = std::numeric_limits::quiet_NaN(); - if (state.previous_frame_start <= transform->frame_start - && transform->frame_start < state.previous_frame_end - && state.previous_frame_end <= transform->frame_end) + if (transform->frame_start < transform->frame_end) { - for (RowNumber i = state.previous_frame_start; i < transform->frame_start; transform->advanceRowNumber(i)) + RowNumber frame_back = transform->prevRowNumber(transform->frame_end); + Float64 back_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, frame_back); + + if (transform->prev_frame_start <= transform->frame_start + && transform->frame_start < transform->prev_frame_end + && transform->prev_frame_end <= transform->frame_end) { - Float64 prev_val = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_VALUE, i); - Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); - Float64 decay = std::exp((prev_t - curr_t) / decay_length); - sum -= decay * prev_val; - count -= decay; + for (RowNumber i = transform->prev_frame_start; i < transform->frame_start; transform->advanceRowNumber(i)) + { + Float64 prev_val = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_VALUE, i); + Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); + Float64 decay = std::exp((prev_t - back_t) / decay_length); + sum -= decay * prev_val; + count -= decay; + } + + { + Float64 decay = std::exp((state.previous_time - back_t) / decay_length); + sum += decay * state.previous_sum; + count += decay * state.previous_count; + } + + for (RowNumber i = transform->prev_frame_end; i < transform->frame_end; transform->advanceRowNumber(i)) + { + Float64 prev_val = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_VALUE, i); + Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); + Float64 decay = std::exp((prev_t - back_t) / decay_length); + sum += decay * prev_val; + count += decay; + } + } + else + { + for (RowNumber i = transform->frame_start; i < transform->frame_end; transform->advanceRowNumber(i)) + { + Float64 prev_val = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_VALUE, i); + Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); + Float64 decay = std::exp((prev_t - back_t) / decay_length); + sum += decay * prev_val; + count += decay; + } } - { - Float64 decay = std::exp((state.previous_time - curr_t) / decay_length); - sum += decay * state.previous_sum; - count += decay * state.previous_count; - } + state.previous_sum = sum; + state.previous_count = count; + state.previous_time = back_t; - for (RowNumber i = state.previous_frame_end; i < transform->frame_end; transform->advanceRowNumber(i)) - { - Float64 prev_val = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_VALUE, i); - Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); - Float64 decay = std::exp((prev_t - curr_t) / decay_length); - sum += decay * prev_val; - count += decay; - } - } - else - { - for (RowNumber i = transform->frame_start; i < transform->frame_end; transform->advanceRowNumber(i)) - { - Float64 prev_val = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_VALUE, i); - Float64 prev_t = WindowFunctionHelpers::getValue(transform, function_index, ARGUMENT_TIME, i); - Float64 decay = std::exp((prev_t - curr_t) / decay_length); - sum += decay * prev_val; - count += decay; - } + result = sum/count; } - state.previous_sum = sum; - state.previous_count = count; - state.previous_time = curr_t; - state.previous_frame_start = transform->frame_start; - state.previous_frame_end = transform->frame_end; - - WindowFunctionHelpers::setValueToOutputColumn(transform, function_index, sum/count); + WindowFunctionHelpers::setValueToOutputColumn(transform, function_index, result); } private: diff --git a/src/Processors/Transforms/WindowTransform.h b/src/Processors/Transforms/WindowTransform.h index e6db8402c5f..424466bca8a 100644 --- a/src/Processors/Transforms/WindowTransform.h +++ b/src/Processors/Transforms/WindowTransform.h @@ -198,8 +198,19 @@ public: ++x.block; } + RowNumber nextRowNumber(const RowNumber & x) const + { + RowNumber result = x; + advanceRowNumber(result); + return result; + } + void retreatRowNumber(RowNumber & x) const { +#ifndef NDEBUG + auto original_x = x; +#endif + if (x.row > 0) { --x.row; @@ -213,12 +224,19 @@ public: x.row = blockAt(x).rows - 1; #ifndef NDEBUG - auto xx = x; - advanceRowNumber(xx); - assert(xx == x); + auto advanced_retreated_x = x; + advanceRowNumber(advanced_retreated_x); + assert(advanced_retreated_x == original_x); #endif } + RowNumber prevRowNumber(const RowNumber & x) const + { + RowNumber result = x; + retreatRowNumber(result); + return result; + } + auto moveRowNumber(const RowNumber & _x, int64_t offset) const; auto moveRowNumberNoCheck(const RowNumber & _x, int64_t offset) const; diff --git a/tests/queries/0_stateless/02020_exponential_smoothing.reference b/tests/queries/0_stateless/02020_exponential_smoothing.reference index bc6d0920705..95f5cb0c310 100644 --- a/tests/queries/0_stateless/02020_exponential_smoothing.reference +++ b/tests/queries/0_stateless/02020_exponential_smoothing.reference @@ -654,23 +654,23 @@ exponentialTimeDecayedAvg 0 48 0.201 ████████████████████ 0 49 0.196 ███████████████████▌ Check `exponentialTimeDecayed.*` supports sliding windows -2 1 3.010050167084 2 3.030251507111 0.993333444442 -1 2 7.060905027605 4.080805360107 4.02030134086 1.756312382816 -0 3 12.091654548833 5.101006700134 5.000500014167 2.418089094006 -4 4 11.050650848754 5.050250835421 5.000500014167 2.209909172572 -5 5 9.970249502081 5 5.000500014167 1.993850509716 -1 6 20.07305726224 10.202013400268 5.000500014167 4.014210020072 -0 7 15.991544871125 10.100501670842 3.98029867414 4.017674596889 +2 1 2.950447180363 1.960397346614 2.970248507056 0.993333444442 +1 2 6.921089740404 4 3.940694040604 1.756312382816 +0 3 11.85222374685 5 4.901483479757 2.418089094006 +4 4 10.831833301125 4.950249168746 4.901483479757 2.209909172572 +5 5 9.772825334477 4.900993366534 4.901483479757 1.993850509716 +1 6 19.675584097659 10 4.901483479757 4.014210020072 +0 7 15.832426341049 10 3.940694040604 4.017674596889 10 8 10.980198673307 10 2.970248507056 3.696727276261 Check `exponentialTimeDecayedMax` works with negative values -2 1 -1.010050167084 -1 2 -1 -10 3 -0.990049833749 -4 4 -0.980198673307 -5 5 -1.010050167084 -1 6 -1 -10 7 -0.990049833749 -10 8 -0.980198673307 -10 9 -9.801986733068 -9.81 10 -9.801986733068 +2 1 -0.990049833749 +1 2 -0.980198673307 +10 3 -0.970445533549 +4 4 -0.960789439152 +5 5 -0.990049833749 +1 6 -0.980198673307 +10 7 -0.970445533549 +10 8 -0.960789439152 +10 9 -9.607894391523 +9.81 10 -9.704455335485 9.9 11 -9.712388869079