This is an automated email from the ASF dual-hosted git repository. kxiao pushed a commit to branch branch-2.0 in repository https://gitbox.apache.org/repos/asf/doris.git
commit 546e33d2a6530f0b4753e0261e9b91ff9dd5fbe2 Author: bobhan1 <[email protected]> AuthorDate: Fri Jul 21 13:57:27 2023 +0800 [Enhancement](window-funnel)add different modes for window_funnel() function (#20563) --- .../aggregate_function_window_funnel.h | 91 ++++++++++-- .../WINDOW-FUNCTION-WINDOW-FUNNEL.md | 6 +- .../WINDOW-FUNCTION-WINDOW-FUNNEL.md | 6 +- .../data/nereids_p0/aggregate/window_funnel.out | 15 ++ .../data/query_p0/aggregate/window_funnel.out | 15 ++ .../nereids_p0/aggregate/window_funnel.groovy | 161 ++++++++++++++++++++ .../suites/query_p0/aggregate/window_funnel.groovy | 162 +++++++++++++++++++++ 7 files changed, 440 insertions(+), 16 deletions(-) diff --git a/be/src/vec/aggregate_functions/aggregate_function_window_funnel.h b/be/src/vec/aggregate_functions/aggregate_function_window_funnel.h index 54ebfe7b28..422d8f1650 100644 --- a/be/src/vec/aggregate_functions/aggregate_function_window_funnel.h +++ b/be/src/vec/aggregate_functions/aggregate_function_window_funnel.h @@ -32,8 +32,10 @@ #include <utility> #include <vector> +#include "common/compiler_util.h" #include "util/binary_cast.hpp" #include "vec/aggregate_functions/aggregate_function.h" +#include "vec/columns/column_string.h" #include "vec/columns/column_vector.h" #include "vec/columns/columns_number.h" #include "vec/common/assert_cast.h" @@ -53,17 +55,35 @@ class IColumn; namespace doris::vectorized { +enum class WindowFunnelMode : Int64 { INVALID, DEFAULT, DEDUPLICATION, FIXED, INCREASE }; + +WindowFunnelMode string_to_window_funnel_mode(const String& string) { + if (string == "default") { + return WindowFunnelMode::DEFAULT; + } else if (string == "deduplication") { + return WindowFunnelMode::DEDUPLICATION; + } else if (string == "fixed") { + return WindowFunnelMode::FIXED; + } else if (string == "increase") { + return WindowFunnelMode::INCREASE; + } else { + return WindowFunnelMode::INVALID; + } +} + template <typename DateValueType, typename NativeType> struct WindowFunnelState { std::vector<std::pair<DateValueType, int>> events; int max_event_level; bool sorted; int64_t window; + WindowFunnelMode window_funnel_mode; WindowFunnelState() { sorted = true; max_event_level = 0; window = 0; + window_funnel_mode = WindowFunnelMode::INVALID; } void reset() { @@ -73,9 +93,12 @@ struct WindowFunnelState { events.shrink_to_fit(); } - void add(const DateValueType& timestamp, int event_idx, int event_num, int64_t win) { + void add(const DateValueType& timestamp, int event_idx, int event_num, int64_t win, + WindowFunnelMode mode) { window = win; max_event_level = event_num; + window_funnel_mode = mode; + if (sorted && events.size() > 0) { if (events.back().first == timestamp) { sorted = events.back().second <= event_idx; @@ -94,25 +117,58 @@ struct WindowFunnelState { } int get() const { - std::vector<std::optional<DateValueType>> events_timestamp(max_event_level); + if (max_event_level == 0) { + return 0; + } + std::vector<std::optional<std::pair<DateValueType, DateValueType>>> events_timestamp( + max_event_level); + bool is_first_set = false; for (int64_t i = 0; i < events.size(); i++) { const int& event_idx = events[i].second; const DateValueType& timestamp = events[i].first; if (event_idx == 0) { - events_timestamp[0] = timestamp; + events_timestamp[0] = {timestamp, timestamp}; + is_first_set = true; continue; } + if (window_funnel_mode == WindowFunnelMode::DEDUPLICATION && + events_timestamp[event_idx].has_value()) { + break; + } if (events_timestamp[event_idx - 1].has_value()) { - const DateValueType& first_timestamp = events_timestamp[event_idx - 1].value(); + const DateValueType& first_timestamp = + events_timestamp[event_idx - 1].value().first; DateValueType last_timestamp = first_timestamp; TimeInterval interval(SECOND, window, false); last_timestamp.template date_add_interval<SECOND>(interval); - if (timestamp <= last_timestamp) { - events_timestamp[event_idx] = first_timestamp; - if (event_idx + 1 == max_event_level) { - // Usually, max event level is small. - return max_event_level; + if (window_funnel_mode != WindowFunnelMode::INCREASE) { + if (timestamp <= last_timestamp) { + events_timestamp[event_idx] = {first_timestamp, timestamp}; + if (event_idx + 1 == max_event_level) { + // Usually, max event level is small. + return max_event_level; + } + } + } else { + if (timestamp <= last_timestamp && + events_timestamp[event_idx - 1].value().second < timestamp) { + if (!events_timestamp[event_idx].has_value() || + events_timestamp[event_idx].value().second > timestamp) { + events_timestamp[event_idx] = {first_timestamp, timestamp}; + } + if (event_idx + 1 == max_event_level) { + // Usually, max event level is small. + return max_event_level; + } + } + } + } else { + if (is_first_set && window_funnel_mode == WindowFunnelMode::FIXED) { + for (size_t i = 0; i < events_timestamp.size(); i++) { + if (!events_timestamp[i].has_value()) { + return i; + } } } } @@ -147,13 +203,17 @@ struct WindowFunnelState { std::inplace_merge(begin, middle, end); max_event_level = max_event_level > 0 ? max_event_level : other.max_event_level; window = window > 0 ? window : other.window; - + window_funnel_mode = window_funnel_mode == WindowFunnelMode::INVALID + ? other.window_funnel_mode + : window_funnel_mode; sorted = true; } void write(BufferWritable& out) const { write_var_int(max_event_level, out); write_var_int(window, out); + write_var_int(static_cast<std::underlying_type_t<WindowFunnelMode>>(window_funnel_mode), + out); write_var_int(events.size(), out); for (int64_t i = 0; i < events.size(); i++) { @@ -169,6 +229,9 @@ struct WindowFunnelState { read_var_int(event_level, in); max_event_level = (int)event_level; read_var_int(window, in); + int64_t mode; + read_var_int(mode, in); + window_funnel_mode = static_cast<WindowFunnelMode>(mode); int64_t size = 0; read_var_int(size, in); for (int64_t i = 0; i < size; i++) { @@ -178,7 +241,7 @@ struct WindowFunnelState { read_var_int(timestamp, in); read_var_int(event_idx, in); DateValueType time_value = binary_cast<NativeType, DateValueType>(timestamp); - add(time_value, (int)event_idx, max_event_level, window); + add(time_value, (int)event_idx, max_event_level, window, window_funnel_mode); } } }; @@ -204,8 +267,7 @@ public: Arena*) const override { const auto& window = assert_cast<const ColumnVector<Int64>&>(*columns[0]).get_data()[row_num]; - // TODO: handle mode in the future. - // be/src/olap/row_block2.cpp copy_data_to_column + StringRef mode = columns[1]->get_data_at(row_num); const auto& timestamp = assert_cast<const ColumnVector<NativeType>&>(*columns[2]).get_data()[row_num]; const int NON_EVENT_NUM = 3; @@ -215,7 +277,8 @@ public: if (is_set) { this->data(place).add( binary_cast<NativeType, DateValueType>(timestamp), i - NON_EVENT_NUM, - IAggregateFunction::get_argument_types().size() - NON_EVENT_NUM, window); + IAggregateFunction::get_argument_types().size() - NON_EVENT_NUM, window, + string_to_window_funnel_mode(mode.to_string())); } } } diff --git a/docs/en/docs/sql-manual/sql-functions/window-functions/WINDOW-FUNCTION-WINDOW-FUNNEL.md b/docs/en/docs/sql-manual/sql-functions/window-functions/WINDOW-FUNCTION-WINDOW-FUNNEL.md index 92a19d0644..fe2fcf4edf 100644 --- a/docs/en/docs/sql-manual/sql-functions/window-functions/WINDOW-FUNCTION-WINDOW-FUNNEL.md +++ b/docs/en/docs/sql-manual/sql-functions/window-functions/WINDOW-FUNCTION-WINDOW-FUNNEL.md @@ -17,7 +17,11 @@ Unless required by applicable law or agreed to in writing, software distributed Searches the longest event chain happened in order (event1, event2, ... , eventN) along the timestamp_column with length of window. - window is the length of time window in seconds. -- mode is reserved for future, not used for now. +- mode can be one of the followings: + - "default": Defualt mode. + - "deduplication": If the same event holds for the sequence of events, then such repeating event interrupts further processing. E.g. the array parameter is [event1='A', event2='B', event3='C', event4='D'], and the original event chain is "A-B-C-B-D". Since event B repeats, the filtered event chain can only be "A-B-C" and the max event level is 3. + - "fixed": Don't allow interventions of other events. E.g. the array parameter is [event1='A', event2='B', event3='C', event4='D'], and the original event chain is A->B->D->C, it stops finding A->B->C at the D and the max event level is 2. + - "increase": Apply conditions only to events with strictly increasing timestamps. - timestamp_column specifies column of DATETIME type, sliding time window works on it. - evnetN is boolean expression like eventID = 1004. diff --git a/docs/zh-CN/docs/sql-manual/sql-functions/window-functions/WINDOW-FUNCTION-WINDOW-FUNNEL.md b/docs/zh-CN/docs/sql-manual/sql-functions/window-functions/WINDOW-FUNCTION-WINDOW-FUNNEL.md index 93567de318..21b073ab0f 100644 --- a/docs/zh-CN/docs/sql-manual/sql-functions/window-functions/WINDOW-FUNCTION-WINDOW-FUNNEL.md +++ b/docs/zh-CN/docs/sql-manual/sql-functions/window-functions/WINDOW-FUNCTION-WINDOW-FUNNEL.md @@ -17,7 +17,11 @@ Unless required by applicable law or agreed to in writing, software distributed 漏斗分析函数搜索滑动时间窗口内最大的发生的最大事件序列长度。 - window :滑动时间窗口大小,单位为秒。 -- mode :保留,目前只支持default。 +- mode :模式,共有四种模式 + - "default": 默认模式。 + - "deduplication": 当某个事件重复发生时,这个重复发生的事件会阻止后续的处理过程。如,指定事件链为[event1='A', event2='B', event3='C', event4='D'],原始事件链为"A-B-C-B-D"。由于B事件重复,最终的结果事件链为A-B-C,最大长度为3。 + - "fixed": 不允许事件的顺序发生交错,即事件发生的顺序必须和指定的事件链顺序一致。如,指定事件链为[event1='A', event2='B', event3='C', event4='D'],原始事件链为"A-B-D-C",则结果事件链为A-B,最大长度为2 + - "increase": 选中的事件的时间戳必须按照指定事件链严格递增。 - timestamp_column :指定时间列,类型为DATETIME, 滑动窗口沿着此列工作。 - eventN :表示事件的布尔表达式。 diff --git a/regression-test/data/nereids_p0/aggregate/window_funnel.out b/regression-test/data/nereids_p0/aggregate/window_funnel.out index b6db6f0046..3396dd90e8 100644 --- a/regression-test/data/nereids_p0/aggregate/window_funnel.out +++ b/regression-test/data/nereids_p0/aggregate/window_funnel.out @@ -11,3 +11,18 @@ -- !window_funnel -- 2 +-- !window_funnel_deduplication -- +2 + +-- !window_funnel_fixed -- +2 + +-- !window_funnel_fixed -- +1 + +-- !window_funnel_increase -- +4 + +-- !window_funnel_increase -- +2 + diff --git a/regression-test/data/query_p0/aggregate/window_funnel.out b/regression-test/data/query_p0/aggregate/window_funnel.out index b6db6f0046..3396dd90e8 100644 --- a/regression-test/data/query_p0/aggregate/window_funnel.out +++ b/regression-test/data/query_p0/aggregate/window_funnel.out @@ -11,3 +11,18 @@ -- !window_funnel -- 2 +-- !window_funnel_deduplication -- +2 + +-- !window_funnel_fixed -- +2 + +-- !window_funnel_fixed -- +1 + +-- !window_funnel_increase -- +4 + +-- !window_funnel_increase -- +2 + diff --git a/regression-test/suites/nereids_p0/aggregate/window_funnel.groovy b/regression-test/suites/nereids_p0/aggregate/window_funnel.groovy index 803c2ad1fe..c2ea9469b7 100644 --- a/regression-test/suites/nereids_p0/aggregate/window_funnel.groovy +++ b/regression-test/suites/nereids_p0/aggregate/window_funnel.groovy @@ -104,4 +104,165 @@ suite("window_funnel") { from ${tableName} t; """ sql """ DROP TABLE IF EXISTS ${tableName} """ + + sql """ DROP TABLE IF EXISTS ${tableName} """ + sql """ + CREATE TABLE IF NOT EXISTS ${tableName} ( + xwho varchar(50) NULL COMMENT 'xwho', + xwhen datetimev2(3) COMMENT 'xwhen', + xwhat int NULL COMMENT 'xwhat' + ) + DUPLICATE KEY(xwho) + DISTRIBUTED BY HASH(xwho) BUCKETS 3 + PROPERTIES ( + "replication_num" = "1" + ); + """ + sql "INSERT into ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 10:41:00.111111', 1)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:02.111111', 2)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:03.111111', 2)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 14:15:01.111111', 3)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 15:05:04.111111', 4)" + qt_window_funnel_deduplication """ + select + window_funnel( + 20000, + 'deduplication', + t.xwhen, + t.xwhat = 1, + t.xwhat = 2, + t.xwhat = 3, + t.xwhat = 4 + ) AS level + from ${tableName} t; + """ + sql """ DROP TABLE IF EXISTS ${tableName} """ + + sql """ DROP TABLE IF EXISTS ${tableName} """ + sql """ + CREATE TABLE IF NOT EXISTS ${tableName} ( + xwho varchar(50) NULL COMMENT 'xwho', + xwhen datetimev2(3) COMMENT 'xwhen', + xwhat int NULL COMMENT 'xwhat' + ) + DUPLICATE KEY(xwho) + DISTRIBUTED BY HASH(xwho) BUCKETS 3 + PROPERTIES ( + "replication_num" = "1" + ); + """ + sql "INSERT into ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 10:41:00.111111', 1)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:02.111111', 2)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 14:15:01.111111', 3)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 15:05:04.111111', 4)" + qt_window_funnel_fixed """ + select + window_funnel( + 20000, + 'fixed', + t.xwhen, + t.xwhat = 1, + t.xwhat = 2, + t.xwhat = 4, + t.xwhat = 3 + ) AS level + from ${tableName} t; + """ + sql """ DROP TABLE IF EXISTS ${tableName} """ + + sql """ DROP TABLE IF EXISTS ${tableName} """ + sql """ + CREATE TABLE IF NOT EXISTS ${tableName} ( + xwho varchar(50) NULL COMMENT 'xwho', + xwhen datetimev2(3) COMMENT 'xwhen', + xwhat int NULL COMMENT 'xwhat' + ) + DUPLICATE KEY(xwho) + DISTRIBUTED BY HASH(xwho) BUCKETS 3 + PROPERTIES ( + "replication_num" = "1" + ); + """ + sql "INSERT into ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 10:41:00.111111', 1)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:02.111111', 2)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 14:15:01.111111', 3)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 15:05:04.111111', 4)" + qt_window_funnel_fixed """ + select + window_funnel( + 20000, + 'fixed', + t.xwhen, + t.xwhat = 4, + t.xwhat = 3, + t.xwhat = 2, + t.xwhat = 1 + ) AS level + from ${tableName} t; + """ + sql """ DROP TABLE IF EXISTS ${tableName} """ + + sql """ DROP TABLE IF EXISTS ${tableName} """ + sql """ + CREATE TABLE IF NOT EXISTS ${tableName} ( + xwho varchar(50) NULL COMMENT 'xwho', + xwhen datetimev2(3) COMMENT 'xwhen', + xwhat int NULL COMMENT 'xwhat' + ) + DUPLICATE KEY(xwho) + DISTRIBUTED BY HASH(xwho) BUCKETS 3 + PROPERTIES ( + "replication_num" = "1" + ); + """ + sql "INSERT into ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 10:41:00.111111', 1)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:02.111111', 2)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:03.111111', 3)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 15:05:04.111111', 4)" + qt_window_funnel_increase """ + select + window_funnel( + 20000, + 'increase', + t.xwhen, + t.xwhat = 1, + t.xwhat = 2, + t.xwhat = 3, + t.xwhat = 4 + ) AS level + from ${tableName} t; + """ + sql """ DROP TABLE IF EXISTS ${tableName} """ + + sql """ DROP TABLE IF EXISTS ${tableName} """ + sql """ + CREATE TABLE IF NOT EXISTS ${tableName} ( + xwho varchar(50) NULL COMMENT 'xwho', + xwhen datetimev2(3) COMMENT 'xwhen', + xwhat int NULL COMMENT 'xwhat' + ) + DUPLICATE KEY(xwho) + DISTRIBUTED BY HASH(xwho) BUCKETS 3 + PROPERTIES ( + "replication_num" = "1" + ); + """ + sql "INSERT into ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 10:41:00.111111', 1)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:02.111111', 2)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:02.111111', 3)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 15:05:04.111111', 4)" + qt_window_funnel_increase """ + select + window_funnel( + 20000, + 'increase', + t.xwhen, + t.xwhat = 1, + t.xwhat = 2, + t.xwhat = 3, + t.xwhat = 4 + ) AS level + from ${tableName} t; + """ + sql """ DROP TABLE IF EXISTS ${tableName} """ } diff --git a/regression-test/suites/query_p0/aggregate/window_funnel.groovy b/regression-test/suites/query_p0/aggregate/window_funnel.groovy index 51a5446c20..83f39ae000 100644 --- a/regression-test/suites/query_p0/aggregate/window_funnel.groovy +++ b/regression-test/suites/query_p0/aggregate/window_funnel.groovy @@ -20,6 +20,7 @@ // and modified by Doris. suite("window_funnel") { + sql "SET enable_nereids_planner=false" def tableName = "windowfunnel_test" sql """ DROP TABLE IF EXISTS ${tableName} """ @@ -102,4 +103,165 @@ suite("window_funnel") { from ${tableName} t; """ sql """ DROP TABLE IF EXISTS ${tableName} """ + + sql """ DROP TABLE IF EXISTS ${tableName} """ + sql """ + CREATE TABLE IF NOT EXISTS ${tableName} ( + xwho varchar(50) NULL COMMENT 'xwho', + xwhen datetimev2(3) COMMENT 'xwhen', + xwhat int NULL COMMENT 'xwhat' + ) + DUPLICATE KEY(xwho) + DISTRIBUTED BY HASH(xwho) BUCKETS 3 + PROPERTIES ( + "replication_num" = "1" + ); + """ + sql "INSERT into ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 10:41:00.111111', 1)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:02.111111', 2)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:03.111111', 2)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 14:15:01.111111', 3)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 15:05:04.111111', 4)" + qt_window_funnel_deduplication """ + select + window_funnel( + 20000, + 'deduplication', + t.xwhen, + t.xwhat = 1, + t.xwhat = 2, + t.xwhat = 3, + t.xwhat = 4 + ) AS level + from ${tableName} t; + """ + sql """ DROP TABLE IF EXISTS ${tableName} """ + + sql """ DROP TABLE IF EXISTS ${tableName} """ + sql """ + CREATE TABLE IF NOT EXISTS ${tableName} ( + xwho varchar(50) NULL COMMENT 'xwho', + xwhen datetimev2(3) COMMENT 'xwhen', + xwhat int NULL COMMENT 'xwhat' + ) + DUPLICATE KEY(xwho) + DISTRIBUTED BY HASH(xwho) BUCKETS 3 + PROPERTIES ( + "replication_num" = "1" + ); + """ + sql "INSERT into ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 10:41:00.111111', 1)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:02.111111', 2)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 14:15:01.111111', 3)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 15:05:04.111111', 4)" + qt_window_funnel_fixed """ + select + window_funnel( + 20000, + 'fixed', + t.xwhen, + t.xwhat = 1, + t.xwhat = 2, + t.xwhat = 4, + t.xwhat = 3 + ) AS level + from ${tableName} t; + """ + sql """ DROP TABLE IF EXISTS ${tableName} """ + + sql """ DROP TABLE IF EXISTS ${tableName} """ + sql """ + CREATE TABLE IF NOT EXISTS ${tableName} ( + xwho varchar(50) NULL COMMENT 'xwho', + xwhen datetimev2(3) COMMENT 'xwhen', + xwhat int NULL COMMENT 'xwhat' + ) + DUPLICATE KEY(xwho) + DISTRIBUTED BY HASH(xwho) BUCKETS 3 + PROPERTIES ( + "replication_num" = "1" + ); + """ + sql "INSERT into ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 10:41:00.111111', 1)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:02.111111', 2)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 14:15:01.111111', 3)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 15:05:04.111111', 4)" + qt_window_funnel_fixed """ + select + window_funnel( + 20000, + 'fixed', + t.xwhen, + t.xwhat = 4, + t.xwhat = 3, + t.xwhat = 2, + t.xwhat = 1 + ) AS level + from ${tableName} t; + """ + sql """ DROP TABLE IF EXISTS ${tableName} """ + + sql """ DROP TABLE IF EXISTS ${tableName} """ + sql """ + CREATE TABLE IF NOT EXISTS ${tableName} ( + xwho varchar(50) NULL COMMENT 'xwho', + xwhen datetimev2(3) COMMENT 'xwhen', + xwhat int NULL COMMENT 'xwhat' + ) + DUPLICATE KEY(xwho) + DISTRIBUTED BY HASH(xwho) BUCKETS 3 + PROPERTIES ( + "replication_num" = "1" + ); + """ + sql "INSERT into ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 10:41:00.111111', 1)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:02.111111', 2)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:03.111111', 3)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 15:05:04.111111', 4)" + qt_window_funnel_increase """ + select + window_funnel( + 20000, + 'increase', + t.xwhen, + t.xwhat = 1, + t.xwhat = 2, + t.xwhat = 3, + t.xwhat = 4 + ) AS level + from ${tableName} t; + """ + sql """ DROP TABLE IF EXISTS ${tableName} """ + + sql """ DROP TABLE IF EXISTS ${tableName} """ + sql """ + CREATE TABLE IF NOT EXISTS ${tableName} ( + xwho varchar(50) NULL COMMENT 'xwho', + xwhen datetimev2(3) COMMENT 'xwhen', + xwhat int NULL COMMENT 'xwhat' + ) + DUPLICATE KEY(xwho) + DISTRIBUTED BY HASH(xwho) BUCKETS 3 + PROPERTIES ( + "replication_num" = "1" + ); + """ + sql "INSERT into ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 10:41:00.111111', 1)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:02.111111', 2)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 13:28:02.111111', 3)" + sql "INSERT INTO ${tableName} (xwho, xwhen, xwhat) VALUES('1', '2022-03-12 15:05:04.111111', 4)" + qt_window_funnel_increase """ + select + window_funnel( + 20000, + 'increase', + t.xwhen, + t.xwhat = 1, + t.xwhat = 2, + t.xwhat = 3, + t.xwhat = 4 + ) AS level + from ${tableName} t; + """ + sql """ DROP TABLE IF EXISTS ${tableName} """ } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
