From f8bf5e5b06ba4367f65690d80263ffdb855d5abb Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Thu, 19 Feb 2026 23:21:05 +0400 Subject: [PATCH 01/48] Clickhouse-Homewok --- dsolovianov/clickhouse/{ => Homework}/image.png | Bin .../{ => Homework}/Типы таблиц - Домашки.sql | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename dsolovianov/clickhouse/{ => Homework}/image.png (100%) rename dsolovianov/clickhouse/{ => Homework}/Типы таблиц - Домашки.sql (100%) diff --git a/dsolovianov/clickhouse/image.png b/dsolovianov/clickhouse/Homework/image.png similarity index 100% rename from dsolovianov/clickhouse/image.png rename to dsolovianov/clickhouse/Homework/image.png diff --git a/dsolovianov/clickhouse/Типы таблиц - Домашки.sql b/dsolovianov/clickhouse/Homework/Типы таблиц - Домашки.sql similarity index 100% rename from dsolovianov/clickhouse/Типы таблиц - Домашки.sql rename to dsolovianov/clickhouse/Homework/Типы таблиц - Домашки.sql From c5a5df7c25be961c46e991ee7c1dd2402fa08a0e Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Thu, 26 Feb 2026 01:54:22 +0400 Subject: [PATCH 02/48] =?UTF-8?q?1)=20=D0=9F=D0=B5=D1=80=D0=B5=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BB=20=D0=B4=D0=BE=D0=BC=D0=B0=D1=88=D0=BA=D1=83?= =?UTF-8?q?=20=D0=B2=20=D0=A2=D0=B8=D0=BF=D1=8B=20=D1=82=D0=B0=D0=B1=D0=BB?= =?UTF-8?q?=D0=B8=D1=86=20=D0=BF=D0=BE=D0=B4=20ON=20CLUSTER.=202)=20=D0=A1?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20=D0=B4=D0=BE=D0=BC=D0=B0=D1=88?= =?UTF-8?q?=D0=BA=D1=83=20=D0=B2=20=D0=A2=D0=B8=D0=BF=D1=8B=20=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D1=85=20-=20=D0=97=D0=B0=D0=B4=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Homework/Типы данных - Домашка.sql | 26 ++++++++++++++++++ .../Homework/Типы таблиц - Домашки.sql | 27 ++++++++++++------- 2 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 dsolovianov/clickhouse/Homework/Типы данных - Домашка.sql diff --git a/dsolovianov/clickhouse/Homework/Типы данных - Домашка.sql b/dsolovianov/clickhouse/Homework/Типы данных - Домашка.sql new file mode 100644 index 0000000..963af35 --- /dev/null +++ b/dsolovianov/clickhouse/Homework/Типы данных - Домашка.sql @@ -0,0 +1,26 @@ +--Типы данных + +--Задача 1 +CREATE TABLE raw_data +ON CLUSTER clickhouse_cluster +( + user_id String, + balance String, + created_at String +) ENGINE = MergeTree ORDER BY tuple(); + +SELECT DISTINCT + toDecimal64OrNull(balance, 2) AS balance_decimal, + toDateTime64OrNull(created_at, 3) AS created_at_date +FROM raw_data +WHERE + toDecimal64OrNull(balance, 2) IS NOT NULL + AND toDateTime64OrNull(created_at, 3) IS NOT NULL + +/* + CAST(balance AS Decimal(10, 2)) - этом случае будет ошибка, так как данный метод не поддеживает NULL + + Следующие два метода по сути своей преобразование типа данных с условием ИЛИ, то есть: +toDecimal64OrNull(balance, 2) - в этом методе на выходе будут корректные данные, в противном случае NULL +toDecimal64OrZero(balance, 2) - аналогично с NULL, только будет ноль. +*/ \ No newline at end of file diff --git a/dsolovianov/clickhouse/Homework/Типы таблиц - Домашки.sql b/dsolovianov/clickhouse/Homework/Типы таблиц - Домашки.sql index 04cda20..af9dcc3 100644 --- a/dsolovianov/clickhouse/Homework/Типы таблиц - Домашки.sql +++ b/dsolovianov/clickhouse/Homework/Типы таблиц - Домашки.sql @@ -1,6 +1,9 @@ --Задача 1: Создай таблицу page_views +DROP TABLE page_views; -CREATE TABLE page_views ( +CREATE TABLE page_views +ON CLUSTER clickhouse_cluster +( user_id UInt64, url String, view_time DateTime @@ -11,7 +14,9 @@ ORDER BY (user_id, view_time); --Задача 2: Создай таблицу users -CREATE TABLE users ( +CREATE TABLE users +ON CLUSTER clickhouse_cluster +( id UInt64, name String, updated_at DateTime @@ -21,7 +26,9 @@ ORDER BY id; -- Задача 3: Создай таблицу region_sales -CREATE TABLE region_sales ( +CREATE TABLE region_sales +ON CLUSTER clickhouse_cluster +( region String, date Date, sales UInt64 @@ -30,17 +37,19 @@ ENGINE = SummingMergeTree() PARTITION BY toYYYYMM(date) ORDER BY (region, date); ---Задача 4.1: Создай таблицу user_metrics +--Задача 4: Создай таблицу user_metrics -CREATE TABLE user_metrics ( +CREATE TABLE user_metrics +ON CLUSTER clickhouse_cluster +( region String, avg_age_state AggregateFunction(avg, UInt8), active_users_state AggregateFunction(uniq, UInt64) ) -ENGINE = AggregatingMergeTree() -ORDER BY region; +ENGINE = AggregatingMergeTree() --Подзадача 4.2 +ORDER BY region; --Подзадача 4.3 ---Задача 4.3: - Вставь данные и Читай их через `avgMerge()` и `uniqMerge()` +--Подзадача 4.4: - Вставь данные и Читай их через `avgMerge()` и `uniqMerge()` INSERT INTO user_metrics SELECT @@ -61,7 +70,7 @@ FROM ) GROUP BY region; ---Задача 4.4: - Читай их через `avgMerge()` и `uniqMerge()` +--Подзадача 4.5: - Читай их через `avgMerge()` и `uniqMerge()` SELECT region, From ae3392a2a3540a7d38f7b5836e40cfa9b1536376 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Thu, 26 Feb 2026 02:05:53 +0400 Subject: [PATCH 03/48] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=B7=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=BB=20=D0=B4=D0=BE=D0=BC=D0=B0=D1=88=D0=BA=D1=83?= =?UTF-8?q?=20=D0=BF=D0=BE=20=D0=A2=D0=B8=D0=BF=D1=8B=20=D1=82=D0=B0=D0=B1?= =?UTF-8?q?=D0=BB=D0=B8=D1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{Типы таблиц - Домашки.sql => CH - Типы таблиц - Домашка.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename dsolovianov/clickhouse/Homework/{Типы таблиц - Домашки.sql => CH - Типы таблиц - Домашка.sql} (100%) diff --git a/dsolovianov/clickhouse/Homework/Типы таблиц - Домашки.sql b/dsolovianov/clickhouse/Homework/CH - Типы таблиц - Домашка.sql similarity index 100% rename from dsolovianov/clickhouse/Homework/Типы таблиц - Домашки.sql rename to dsolovianov/clickhouse/Homework/CH - Типы таблиц - Домашка.sql From 555b38e192e1ab2d61b5302b493c0860ebb60ce1 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Thu, 26 Feb 2026 02:06:46 +0400 Subject: [PATCH 04/48] delete --- .../Homework/CH - Типы таблиц - Домашка.sql | 81 ------------------- 1 file changed, 81 deletions(-) delete mode 100644 dsolovianov/clickhouse/Homework/CH - Типы таблиц - Домашка.sql diff --git a/dsolovianov/clickhouse/Homework/CH - Типы таблиц - Домашка.sql b/dsolovianov/clickhouse/Homework/CH - Типы таблиц - Домашка.sql deleted file mode 100644 index af9dcc3..0000000 --- a/dsolovianov/clickhouse/Homework/CH - Типы таблиц - Домашка.sql +++ /dev/null @@ -1,81 +0,0 @@ ---Задача 1: Создай таблицу page_views -DROP TABLE page_views; - -CREATE TABLE page_views -ON CLUSTER clickhouse_cluster -( - user_id UInt64, - url String, - view_time DateTime - ) -ENGINE = MergeTree() -PARTITION BY toYYYYMM(view_time) -ORDER BY (user_id, view_time); - ---Задача 2: Создай таблицу users - -CREATE TABLE users -ON CLUSTER clickhouse_cluster -( -id UInt64, -name String, -updated_at DateTime - ) -ENGINE = ReplacingMergeTree(updated_at) -ORDER BY id; - --- Задача 3: Создай таблицу region_sales - -CREATE TABLE region_sales -ON CLUSTER clickhouse_cluster -( -region String, -date Date, -sales UInt64 - ) -ENGINE = SummingMergeTree() -PARTITION BY toYYYYMM(date) -ORDER BY (region, date); - ---Задача 4: Создай таблицу user_metrics - -CREATE TABLE user_metrics -ON CLUSTER clickhouse_cluster -( -region String, -avg_age_state AggregateFunction(avg, UInt8), -active_users_state AggregateFunction(uniq, UInt64) - ) -ENGINE = AggregatingMergeTree() --Подзадача 4.2 -ORDER BY region; --Подзадача 4.3 - ---Подзадача 4.4: - Вставь данные и Читай их через `avgMerge()` и `uniqMerge()` - -INSERT INTO user_metrics -SELECT - region, - avgState(age) AS avg_age_state, - uniqState(toUInt64(user_id)) AS active_users_state -FROM -( - SELECT 'Samara' AS region, 25 AS age, 1 AS user_id - UNION ALL - SELECT 'Moscow', 30, 2 - UNION ALL - SELECT 'Moscow', 22, 3 - UNION ALL - SELECT 'Samara', 22, 4 - UNION ALL - SELECT 'Sochi', 34, 5 -) -GROUP BY region; - ---Подзадача 4.5: - Читай их через `avgMerge()` и `uniqMerge()` - -SELECT - region, - avgMerge(avg_age_state), - uniqMerge(active_users_state) -FROM user_metrics -GROUP BY region; - From 13f1c9af89d523b8bfaadf3cb221400eadc32b72 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Thu, 26 Feb 2026 02:07:40 +0400 Subject: [PATCH 05/48] new vers. --- .../Homework/Типы таблиц - Homework.sql | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 dsolovianov/clickhouse/Homework/Типы таблиц - Homework.sql diff --git a/dsolovianov/clickhouse/Homework/Типы таблиц - Homework.sql b/dsolovianov/clickhouse/Homework/Типы таблиц - Homework.sql new file mode 100644 index 0000000..af9dcc3 --- /dev/null +++ b/dsolovianov/clickhouse/Homework/Типы таблиц - Homework.sql @@ -0,0 +1,81 @@ +--Задача 1: Создай таблицу page_views +DROP TABLE page_views; + +CREATE TABLE page_views +ON CLUSTER clickhouse_cluster +( + user_id UInt64, + url String, + view_time DateTime + ) +ENGINE = MergeTree() +PARTITION BY toYYYYMM(view_time) +ORDER BY (user_id, view_time); + +--Задача 2: Создай таблицу users + +CREATE TABLE users +ON CLUSTER clickhouse_cluster +( +id UInt64, +name String, +updated_at DateTime + ) +ENGINE = ReplacingMergeTree(updated_at) +ORDER BY id; + +-- Задача 3: Создай таблицу region_sales + +CREATE TABLE region_sales +ON CLUSTER clickhouse_cluster +( +region String, +date Date, +sales UInt64 + ) +ENGINE = SummingMergeTree() +PARTITION BY toYYYYMM(date) +ORDER BY (region, date); + +--Задача 4: Создай таблицу user_metrics + +CREATE TABLE user_metrics +ON CLUSTER clickhouse_cluster +( +region String, +avg_age_state AggregateFunction(avg, UInt8), +active_users_state AggregateFunction(uniq, UInt64) + ) +ENGINE = AggregatingMergeTree() --Подзадача 4.2 +ORDER BY region; --Подзадача 4.3 + +--Подзадача 4.4: - Вставь данные и Читай их через `avgMerge()` и `uniqMerge()` + +INSERT INTO user_metrics +SELECT + region, + avgState(age) AS avg_age_state, + uniqState(toUInt64(user_id)) AS active_users_state +FROM +( + SELECT 'Samara' AS region, 25 AS age, 1 AS user_id + UNION ALL + SELECT 'Moscow', 30, 2 + UNION ALL + SELECT 'Moscow', 22, 3 + UNION ALL + SELECT 'Samara', 22, 4 + UNION ALL + SELECT 'Sochi', 34, 5 +) +GROUP BY region; + +--Подзадача 4.5: - Читай их через `avgMerge()` и `uniqMerge()` + +SELECT + region, + avgMerge(avg_age_state), + uniqMerge(active_users_state) +FROM user_metrics +GROUP BY region; + From 8076bfd5ed82db2ed02096d392942c13ae18ce96 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Thu, 26 Feb 2026 02:10:30 +0400 Subject: [PATCH 06/48] =?UTF-8?q?=D0=A2=D0=B8=D0=BF=D1=8B=20=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D1=85=20-=20=D0=97=D0=B0=D0=B4=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{Типы данных - Домашка.sql => Типы данных - Homework.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename dsolovianov/clickhouse/Homework/{Типы данных - Домашка.sql => Типы данных - Homework.sql} (100%) diff --git a/dsolovianov/clickhouse/Homework/Типы данных - Домашка.sql b/dsolovianov/clickhouse/Homework/Типы данных - Homework.sql similarity index 100% rename from dsolovianov/clickhouse/Homework/Типы данных - Домашка.sql rename to dsolovianov/clickhouse/Homework/Типы данных - Homework.sql From 266da092457be285a5552c79883f9de76fa1e101 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Thu, 26 Feb 2026 02:12:05 +0400 Subject: [PATCH 07/48] delete --- .../Homework/Типы данных - Homework.sql | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 dsolovianov/clickhouse/Homework/Типы данных - Homework.sql diff --git a/dsolovianov/clickhouse/Homework/Типы данных - Homework.sql b/dsolovianov/clickhouse/Homework/Типы данных - Homework.sql deleted file mode 100644 index 963af35..0000000 --- a/dsolovianov/clickhouse/Homework/Типы данных - Homework.sql +++ /dev/null @@ -1,26 +0,0 @@ ---Типы данных - ---Задача 1 -CREATE TABLE raw_data -ON CLUSTER clickhouse_cluster -( - user_id String, - balance String, - created_at String -) ENGINE = MergeTree ORDER BY tuple(); - -SELECT DISTINCT - toDecimal64OrNull(balance, 2) AS balance_decimal, - toDateTime64OrNull(created_at, 3) AS created_at_date -FROM raw_data -WHERE - toDecimal64OrNull(balance, 2) IS NOT NULL - AND toDateTime64OrNull(created_at, 3) IS NOT NULL - -/* - CAST(balance AS Decimal(10, 2)) - этом случае будет ошибка, так как данный метод не поддеживает NULL - - Следующие два метода по сути своей преобразование типа данных с условием ИЛИ, то есть: -toDecimal64OrNull(balance, 2) - в этом методе на выходе будут корректные данные, в противном случае NULL -toDecimal64OrZero(balance, 2) - аналогично с NULL, только будет ноль. -*/ \ No newline at end of file From f0e4c59112bfb68d6ced13ceb643cbdb52462d51 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Thu, 26 Feb 2026 02:13:06 +0400 Subject: [PATCH 08/48] =?UTF-8?q?=D0=A2=D0=B8=D0=BF=D1=8B=20=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D1=85=20v.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Homework/Homework - Типы данных.sql | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 dsolovianov/clickhouse/Homework/Homework - Типы данных.sql diff --git a/dsolovianov/clickhouse/Homework/Homework - Типы данных.sql b/dsolovianov/clickhouse/Homework/Homework - Типы данных.sql new file mode 100644 index 0000000..963af35 --- /dev/null +++ b/dsolovianov/clickhouse/Homework/Homework - Типы данных.sql @@ -0,0 +1,26 @@ +--Типы данных + +--Задача 1 +CREATE TABLE raw_data +ON CLUSTER clickhouse_cluster +( + user_id String, + balance String, + created_at String +) ENGINE = MergeTree ORDER BY tuple(); + +SELECT DISTINCT + toDecimal64OrNull(balance, 2) AS balance_decimal, + toDateTime64OrNull(created_at, 3) AS created_at_date +FROM raw_data +WHERE + toDecimal64OrNull(balance, 2) IS NOT NULL + AND toDateTime64OrNull(created_at, 3) IS NOT NULL + +/* + CAST(balance AS Decimal(10, 2)) - этом случае будет ошибка, так как данный метод не поддеживает NULL + + Следующие два метода по сути своей преобразование типа данных с условием ИЛИ, то есть: +toDecimal64OrNull(balance, 2) - в этом методе на выходе будут корректные данные, в противном случае NULL +toDecimal64OrZero(balance, 2) - аналогично с NULL, только будет ноль. +*/ \ No newline at end of file From f7b9920af2f7251ac0340841cbcbe149cb7eedcb Mon Sep 17 00:00:00 2001 From: dmitry solovianov Date: Fri, 27 Feb 2026 19:02:32 +0400 Subject: [PATCH 09/48] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=BC=D0=B0=D1=88=D0=BA=D1=83=20=D0=A2=D0=B8=D0=BF?= =?UTF-8?q?=D1=8B=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Перезалью в новой ветке --- .../Homework/Типы таблиц - Homework.sql | 81 ------------------- 1 file changed, 81 deletions(-) delete mode 100644 dsolovianov/clickhouse/Homework/Типы таблиц - Homework.sql diff --git a/dsolovianov/clickhouse/Homework/Типы таблиц - Homework.sql b/dsolovianov/clickhouse/Homework/Типы таблиц - Homework.sql deleted file mode 100644 index af9dcc3..0000000 --- a/dsolovianov/clickhouse/Homework/Типы таблиц - Homework.sql +++ /dev/null @@ -1,81 +0,0 @@ ---Задача 1: Создай таблицу page_views -DROP TABLE page_views; - -CREATE TABLE page_views -ON CLUSTER clickhouse_cluster -( - user_id UInt64, - url String, - view_time DateTime - ) -ENGINE = MergeTree() -PARTITION BY toYYYYMM(view_time) -ORDER BY (user_id, view_time); - ---Задача 2: Создай таблицу users - -CREATE TABLE users -ON CLUSTER clickhouse_cluster -( -id UInt64, -name String, -updated_at DateTime - ) -ENGINE = ReplacingMergeTree(updated_at) -ORDER BY id; - --- Задача 3: Создай таблицу region_sales - -CREATE TABLE region_sales -ON CLUSTER clickhouse_cluster -( -region String, -date Date, -sales UInt64 - ) -ENGINE = SummingMergeTree() -PARTITION BY toYYYYMM(date) -ORDER BY (region, date); - ---Задача 4: Создай таблицу user_metrics - -CREATE TABLE user_metrics -ON CLUSTER clickhouse_cluster -( -region String, -avg_age_state AggregateFunction(avg, UInt8), -active_users_state AggregateFunction(uniq, UInt64) - ) -ENGINE = AggregatingMergeTree() --Подзадача 4.2 -ORDER BY region; --Подзадача 4.3 - ---Подзадача 4.4: - Вставь данные и Читай их через `avgMerge()` и `uniqMerge()` - -INSERT INTO user_metrics -SELECT - region, - avgState(age) AS avg_age_state, - uniqState(toUInt64(user_id)) AS active_users_state -FROM -( - SELECT 'Samara' AS region, 25 AS age, 1 AS user_id - UNION ALL - SELECT 'Moscow', 30, 2 - UNION ALL - SELECT 'Moscow', 22, 3 - UNION ALL - SELECT 'Samara', 22, 4 - UNION ALL - SELECT 'Sochi', 34, 5 -) -GROUP BY region; - ---Подзадача 4.5: - Читай их через `avgMerge()` и `uniqMerge()` - -SELECT - region, - avgMerge(avg_age_state), - uniqMerge(active_users_state) -FROM user_metrics -GROUP BY region; - From 3acf36e7c82a0105c8de0a23c5e8c908f1a60b48 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Fri, 27 Feb 2026 22:08:09 +0400 Subject: [PATCH 10/48] =?UTF-8?q?+=D0=97=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=202=20=D0=B2=20=D0=A2=D0=B8=D0=BF=D1=8B=20=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D1=85=20-=20Homework?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Homework/Homework - Типы данных.sql | 37 +++++++++++++++++- .../Homework/Типы данных - Задача 2.png | Bin 0 -> 112412 bytes .../{image.png => Типы таблиц - Homework.png} | Bin 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 dsolovianov/clickhouse/Homework/Типы данных - Задача 2.png rename dsolovianov/clickhouse/Homework/{image.png => Типы таблиц - Homework.png} (100%) diff --git a/dsolovianov/clickhouse/Homework/Homework - Типы данных.sql b/dsolovianov/clickhouse/Homework/Homework - Типы данных.sql index 963af35..f15301b 100644 --- a/dsolovianov/clickhouse/Homework/Homework - Типы данных.sql +++ b/dsolovianov/clickhouse/Homework/Homework - Типы данных.sql @@ -7,7 +7,7 @@ ON CLUSTER clickhouse_cluster user_id String, balance String, created_at String -) ENGINE = MergeTree ORDER BY tuple(); +) ENGINE = MergeTree ORDER BY tuple(); SELECT DISTINCT toDecimal64OrNull(balance, 2) AS balance_decimal, @@ -23,4 +23,37 @@ WHERE Следующие два метода по сути своей преобразование типа данных с условием ИЛИ, то есть: toDecimal64OrNull(balance, 2) - в этом методе на выходе будут корректные данные, в противном случае NULL toDecimal64OrZero(balance, 2) - аналогично с NULL, только будет ноль. -*/ \ No newline at end of file +*/ + +--Задача 2 +CREATE TABLE events +ON CLUSTER clickhouse_cluster +( + event_id String, + event_date String, -- форматы: "2023-01-01", "01.02.2023", "invalid" + event_time String -- форматы: "12:30:45", "25:99:99" +) +ENGINE = MergeTree +ORDER BY event_id; + +--Заполнил данными для проверки +INSERT INTO events (event_id, event_date, event_time) VALUES +('1', '2023-01-01', '12:30:45'), +('2', '01.02.2023', '08:15:00'), +('3', 'invalid', '25:99:99'), +('4', '2023-05-20', 'invalid'), +('5', '31.12.2023', '23:59:59'); + +SELECT * FROM events; + +SELECT DISTINCT + toDate(DateTime_Valid) AS Event_Date, + toHour(DateTime_Valid) AS Event_Hour, + DateTime_Valid +FROM ( + SELECT + parseDateTimeBestEffortOrNull(concat(event_date, ' ', event_time)) AS DateTime_Valid + FROM events +) +WHERE DateTime_Valid IS NOT NULL; + diff --git a/dsolovianov/clickhouse/Homework/Типы данных - Задача 2.png b/dsolovianov/clickhouse/Homework/Типы данных - Задача 2.png new file mode 100644 index 0000000000000000000000000000000000000000..3e8757a70e49bd7cec059bddf534fb262cd007c6 GIT binary patch literal 112412 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

1Bor0tk7k1}a_EU$IX8@lzF#ed0{Q|>sP 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

S6sXME1(=eOFFI)}P3ea&K?6G^nTa z&yoPiz9UfY{vX_XydR>TcaY|PqFK1XN_kZMJ+w^2H`rQn(qee})RF?O)42wJ0~E9gi;2?TJ!&U!Cn+<7Pq$m)?l$ z=ox&--%W^=;{ZD>aAq+4#Nx|;8$lcPl=1;e5LdeGv`0r)q?x0=9)`ZV37z?DLlN^` ze?vU11XwjSRaI7lev$&UYUXWElM+ZC-x*3sS<}Uov7DM(&>=L5)vW&%Ikc$dpo979 z#Gttgactu|b6@wiJ+De#<-aD^&wm`E=OJ9w0$hy~mw@XM?C$;(zq#go4F9mC4ySBF z;$#n^{zK&<7VqtOXAFbibijCz=Y`m2ed_h_>8s<0+oM9+!1sCUadIQnkjpnfew(rj z>m9@YnR25rkRbJKTT)aEf3Bx(32sFJS~Pn$qsf8bdP8cSwu(&yhm-mz2k^A& z!ZYuco5vzHdRnrLv9O-L{WPV@M#0)hP5A(|VuptqdfNTs*O%cH4jE$Aox9^tz#!xq6@bd&9}&(PlY{S2`Bq(sdKvDY&@Rfw|x*PDg5c63~rNI z2TSzfur<5i8)=aSXh4$!Vzt_A92+De=&GDDR6^tBEw9xxt=uhOl;XqR@|&!citQMUUnvfj7>v`S#l5ksBgf$8kRX z&}F~S`t+^&QB(QDBCW=NCO8Bty^9RsV@J^7ZzsI68njU$YYeRKrlnBbd!BT6A!$e$ zVhw`+M6>CtG{C_kpY^&G7F%VJ2>M|^fh zY8#N6G4vVBBsVs*^!3TC6Fz?oeISIh3#b z$S=fQdX|=I=j)fisMS9IA2f(MtHCO_by2JBmSK;j8FpTDtV6D0Popn?tZuS3*bPam z@E{GH)(H5;nRH(V7Rw zz}65w5QS?5ja{jZRMzaY*tJ%W6xXIWXkfqVI@^@Y7Uw=iKX5|k$+E_XzlKeb)f@=b zG6BzD=|GhdMIw;4lRqu=PCpE zchcj8kqvKRIy7=xWn^7Gx`cRk86TVWCSBCPaNpGp$y({dtLGKg?gr7MtTLSnUx+US z)o=mOj~sMsG+X!rgTPax9;1Q>{D-F7MSlG!8A1gT&XcF^j?D-%$sV49&Go!n$8U8= zFESGzd1a%X>GUc$)#WF@vy!EXEJs}IZdX%>R@?8)DnGJtlGc{<9*9tA7-MjK0MaBv_`)XCA^y{F}Ok-i-lPTth z-J-)$ooyfK8mUivPIAGut2FK;JV-va2dV;bZjU!{?e@0t&s<*u-v=ujDfnT|*0jH9 zX*in50Nd#iAr=UI(k@kDbvZG8gpc2@UtU>fkRR(j4PZjU6?Vkv-|7756`K=CGG<}t zo~d&>V7iG>s0l)mqkIvbiSlUbWm<2~;mB9*>K}G#IgAyp=4CB)0;C9ihlpdF=Shks z?GL_OI({Dqw{C>Pw^A4x8Rb2dv391=tSp9_UlXZ2OTB~g1_zZ&P<#bO7&4VH5(R~m zgg8?Fx1zERf~-gm$+=>EPUrQ$woOFG20I-|J_11SkshY?@Y{1o?Ma%x!woW06cR=F z1CH*I)FEIARmXGX9OmB+#Pv;n5z1y+=)PPEw+timK^RNBsqo0pHe6*)hmaGm42b8a;IBF}6Qe{$^_tlM?~}Jj8UTM4WiwjY;@nPdTVN3?&5p^wMy{{*5WkgnWuiZsPo64Rl zL`N^$Qd4|_c_ELpI9Ce4yL|zBdGgx_`c*#JJX@}6VAvvMM#>&Tv1z>3{Uot`n}f(F zalYBjbNu;0*xLRzGjMh0T%UOsoYWrn*QauKENAD(?hRL(xOdOHhqhH~#is8R3!gby z*UKp@ZSg1Cd7u`)d9EJNrh$V1V~|+msu+fdkJc9EEA{qR0)2BpT<7gO7ImSeF2x!6 z*-!jd#{tC3kbruGmWA9)-u{4A2TjS@9}G=ayF~Gx{2m3q)93+?)I0T;PdA$zKQ+@| z{LqCxR_n1!f9=+!xi0(?F#x9Kw4YDGb-H(a7sWel(iPsTa-I9Z+5Ysav-cHTr`qF$ z4LeXCY6PuY28^atK_X{@{T8@eA96ON>muHLYFmO&s#l|FV%ujo>rQoe&{VOR+3~lh z?eiSK#-F&l!OQ9A&pN_k_PC_piF-ywokc^zoGa|S_|)BW)m2m+@%nYeSwjH-phpx; zWB=IFK~k$Q3qEts*x`4(b-ZA|op+?nGe#Y54q76sCr=ZZ^Y>k=NNa3qTPmOQJ1mN_ z9Fgm_3?RN)nhLlayp6o7je=TAP267~FR*@?%Di}CB%iAIN@efw^d$ZFyH{1*yRbKgsU5)lO_LZZniHnl zflMUK@-kUXNMzwfN znT~ZkV%UN4V26ai?mXt!%ZlJw0d~iF{1fM?l2a8H0q2SFA=3^D@QSYG=W)iNWid7n z-?+Hb#c_5S8gdf zo$ck`NwP2av_en@2zm-Rr^?2_7?}td`^hRdVjWj54#vUU>BClOY zW_}+q)Z^Nno`Y%3?BDb_5Ko#~?fI)~nfhT7aB%e%re`1^F`+*j~wl`}arlk_mkI8e(Kx!TZBKt#q}lTHqQy-JXWtk7H&QbuB-9Q zk+Y%1?ppG&zt+^i#iNXjNa7|mpT>*g;d7-|eVc3%W-}rq$PL_VDKPxSG*%1%u06!l zZfh(z-}M59HI-QHg1dquxhOvV~aIl$94qy9NUfTR7-!Ba z$5^5UwAH>9R*9=Qg4^sTrZkk5p{Lz0XKW%or7wXP;$WXb{vn+xf%S224H0PHFuW!bL*Njz9Ui z@Kz`?^Bs?Dt_NZlr8C8#?Lo=ooOqOWOvL`EXv8ZG!YYUd+(@$;+|6$as&tIec0-Pv zHyRU~2tF`j0tZOJlDrubD2w<`BRRD-a<#*|doeEby$!%{$A*@`#PeZRvnh_(>|EMf zqr6Bu;ui;sDn~i$=B9=szkV^sS>j`N$#in)!Zls>d%}-BX8pwja|oRe^J8(*t~*91 zkR@sTn)Q*fLL;me8L@W*s5SAa?V}k| zmRUxuky&)k?r*waO)%CNiYTLO0JTb`vTnx7eALEpHXP(+XEwj+fRM|SfLY^!96(Ms zgs-jpqDQhGG z|atuOoyeO zSU^7X-NJ5(@hK#o;l&D?b<12+w}Ac*SC!zHuiJmIG68k zcYhGvZKY))Le6rU@HH_|vod9Ar7~uG={J60h1M-zR)$(hoT&Zp z%l8g_2L^8$Ed`f(UHL5_JIvQGf`Vo&Ebi!>rHTZ$2iAk`qQPRnP0IJ>i{JA^9P%WV z>!+2*&On{JY;x4&Lwko>M&;NS6TuhL9W2j#)Ie$YuEP6tx45p?UdFn!hyw~K5&+_j}f!G zk34)!dV*AzQ$@BHpYdRxvBG*ul zE?V>;(qDnvnaT^xeL&gSysi$rqY*uTvwpbjMP*l`{9pHx5IMs5u41S?oH~a&n4hd zPy@C7iN96Bu6Vp%+$i+vZ-hHPCr^FH$($;dw^JivA3<6-k}G|(J&&`VC`v;;9f{%~ z2Xk$aqo8?A4CUcPW)o+wbx#IiH8wM6j(xVp?uGhMP6WGoFS1b znF^7yweHz7`b2kYng4&QQm9A7jN`&sBr_+WdJ{_N~-J$C-LRM z#K1E1{f2DG=Lp{7C97Zd8XgBfI1LKZ*mT{Y*uC_+64rCE<>pxPqA^Zu9=E*?%k^9| zBp;k|dT}{AcA!vUDmu>pbmzvbW;?GaUD56CqQBUiGtv2gll(FFd)entwl9G9z;oj1 z?m;qsN8$HP{rcoo@=QO8UCj^2f>^ZECo@+p0%uXF>=g&bfGGCC`Y`dqnAGEV+eUy= z;3cYQp;lzNTgT1m#k52%E>_31^!d2$e6-o;C-m?TBN@?%PZN@-S}_kVdKx=#PL@2+x+peq zDV^}57Jq2cDx7223qnI`nGmst^4={QVN?gwCc7P}zHd6dAJK4*Kb6WPcYYrs_t2c< zn{u(G!;ksG+^7@y;Z=sb)+pzQucCte6+)*u7FJwSg#+m)$%T^Uy+!f`^2`oIi-eh% z6{Ei_HIIrHC`cZb3kGqRhmC(8DHG0R8l-^CwKl(&o_Lk#u$!F|gdo#SpUtebZ%xPX z@=+KyK_C_68JSO8RRCnrF&!)B1?Gxe&==i1;!`7trzAK(X0fQL*Ok(x#o7RhywZ9y z5a_M_G=U3AG6+kR50!E1sT!T()1YKVEpK0Vk|)AmtaOi2c~@49QI=a?RTzoC?z-|p zb?P4hS(=|~!vrAynmkAQ@|83=l>=qn_RjUi=li&1M$6fGrxrB>QFMG36hm_kO7A|s zdZ-8C;E=%$i$39R4{+ORK-!52xZdw_nSPg^+y78lYmYN3Dn!Gcy%)8422BxC@xgOG zm;Hu8fTYriTJLI!q79>#i5Mlb=SU#Xy>xph!Q)EwjFi}-6N(%9jmD>1@sUq~+WGXp zR>EvSF&nTJ_dR!Ox4x5nbpHkI^5EC_s#do^RtX2YR2CG2Kq^*3XE?i*%O{1zBIIrl z%@V(2V?J!-&=HpCLOTH$yb9fR(1nFXvlP+Z-X0|0-r_L~DM;K^+f^;{>)(py#=(%| zSi8(4qf0VmhDwe`ucf#2uQ|39$af4W@5=*(RjxJSRPoN3FSUP+Jt!xs3hhMj`re!M z-c}x(mcu#;=VHTfBtpsjLo3NIhMi*`lOKZuTbPvp-~)pgZf}BQ_WB92>CBhH-D-^x zrm#uv2ncfK}g6IPBW`q5qy^oM#kHYIbC1UsJ3?zR?2&WC&qwx=qBdgs?<5)7_U z1X||jPHk8TARE!LMe=0A&1QV$Gc2m`yic1$-k{seWilhCrq!3 zW&-lMBIkOq&<*;cDY$sp(g{CacNy~2F}M*^bo6TOBa|Miwww&+{tWlVLGF;uPoyv( z&e$#&niEju6Wr7F!#yZnHk>H8sIICct$-tsg02>mT~SmReD~KYrl|3Cm*i*o7!7oe zBJ;uSuC4LEmix4PiQGmWbra2V?(-BQ;UTW_7m=<==N{}hLFZkL`=9Rzw`dZ3@aUK|(5TDko>_i8o8o2DRtqnjVI0 zbJ!|**Fy@8&va7)=BYcERLPBw>@t1Fy?bz(ww@EYdkR}*@dBA==`Xl<>LmA+@T&hY>{e`ZRY9$q9lSKIqT0K)##dt59qPai@+#=Bgc0RDNFDD(auX zX^QGJ5#5Vyc>8%#cv0BARln)nZ1Xtfxjd%Z%mwpP5<7f4PwZ~NP&m~FyZ+LllU?$a zc)gGy0$rKI3KaW=oS?y*#Xe%k5qGu%PtNLxKfOg#gC4&1#9nCqWPYgns5mz=kBE&$ zXLW7z+%MEWxZ`X^ul;Qo!I(YD^rkDs4EN9Thpk=n@dBvM9+x89_lG?^YrLrG zMJ_1=WojhcAkoK{gC-+Laf-+(7i4jYY3fsp+5PWF*T2|`KEAogxEi6`Ju6?P+^F1G z!_C%rG~OLBaGZUZ94UfnEMRA`e6{LYjNcG$QSFb0A!s-nFIm>E+0<&R;J&xqqBMdB zdG)60#%`Vcbot``o#{|ufdG`(edH4P56E( z@_Y+ocV<7<;ZgmFsvCwMi(Lpus2ZK3@!1$J`E`^WTE^ZK-1@2zfIk+Y-MsJ*9z3u{ zD}RM*NdmZ%0Q;eK*bCiY*1E9bUo(1&=!(7lT_XjA#Lf-9%?2oQZcg<>I_RCGlRaWU zZAkzvbwYu%vU0WkVqmStJ1##Se2hjQ0DxkcR^ElOS}-Tc~`rO!e=QQXio`zv^Vu#(6S;!`_F0}G8*bz_6g(${>~17 zr@H>TS_hg@{((3DDW0bZwIS_@ZDQmU{>}b~|D>WkZRh4Tb%|*-@qrqy)iw~Lot=%# z;#bWkg3R{lu!(PhFpBcp{Z3CVx{=2;=l6?(5WOY^W~B#0omJ?-JS@ z&$syIjwfqDK}D>=j^9YFzr?4ft%={`l*tXIzX}^KKRUpD%{!W%r`r63rmt_q6akU;IBVmPI+qMu% zD=#Qtljkntuh+s=F-7-uBagJGUM?r!OuDEWAvn48>!%5)5vI=Ip*QW+WAl~yew1k9~ywM-{qv6jrzvtYQATs?4{ zRNY5euM^K#1)q*)T!{h!v4XA$g}hQ=a$J+NcU=?0@jGtfCGDP%Gt=0XGggh#(@C6b z!XpC|X~YFb2S|6{a@J*tSzD8m}78aPes$X`fm8U?Aw z;#~e5)Ng7C&|?TlE*aRpp{{~q66NMaSyL(yZ!>K;+mA@HHYOh6?cJugzhc9KTs?Y}q0ml-Od=&TaqQWj4YiTuT%;oGeU+{`>y-%G|KhaZQV!x8m zvSbZ8p-P708bMOy@esmNy{q{8y0mSxj3Zj!^_>6cCUox}c|Y8i?lKG3r`YgVhx!M0 zo0fq_ctHLTm3b}~-)6VsAMs`{2Y-oK6Is@LriZl*CSOaV7dC0kP)5VZOgwni@tKH!G21%la6+D9 zQ540pYU3M}*Lv5L9jW#2mJC%R24T0aJn0MdUJ>d(P{v5kSu@Wej2t z2)Ajk_jhw}SD->Vjaeb!dBtY)Vq0n;API-(mCfMj*Ges^eRvIrW#jcB!@+r`SCQl` z2|txNdPyS4^*vGIWIM}qh>C4T?>$7eoP9_Pq;Bk0uN-Eh;{^d7b#+cWul4;bte^9R zc@<+PXJ=`PKt2en8Xi93m6N6T5eqU_=Ui0#)oiTTu-dW5EBX5BBBN37%{$JXSAz#L z`i2wUnT$EFTrHuL`yz>vlxEvk#1lju5%(hUYiR6t&UWmxpH0`&QQhU-n@8b%_%$HI zX`6uguFOJB2j^<2C$W%vBi3xikY4+|?RGo6etej;!(&Q^u;y*`tBY7UY_h>9B4mxe*lTSWkel$`}WJ`XiKM(=C z{~1cCW#gphdMEd^IHtKwPYc+Pyn>ST=^a^%g*0_CxuQ<93 ztcqo;#Z75AA2_v~V`e1!yJdS9aYn@sYcizfk_HcSBtB6&=OGodc95V@ zdx@Zh?MQaTj5@IOH(pYs0vef%Ex~68-^g1x)Ga%9#pM`P3Q{7gX;mSUnvgXhyKf(eg`VCiz3|un0shS1i2%U$&y$BU>$P z51i%j*=*&l$nxzc@AH9gj7pldGztncl7fNDzH7m3=z|%{hn1aI4dz0IET~Jvn}2+k z2a-UTl{{knFsPxtS{)7n!3M5!SFo(9<&!5*l7ME8trLH5=13n3yz=4&zRgs1I@`!l zmNh)SCfFfvNTe6mbr1k2#6Swo+A@tG7h^;T2$F%tj?(&bK}TxAA0Xv@<<`=D8&TG1 z;gbL;8toFSe}(1PRQGx$3a5U zeoiJWFK#K6?Y{J7>c;=1e~UQ$!C@P-F$BlOnrQrL$m07tk&W*9Yg^ZEf|RF;74lJ> z6@||~Jyp?J@u+Wj)KX;2(J~`y;+oVoRQoI(_>rm4>k^xeFXui_y?}xqfXZJCVV3^c zc){&fEZ^*!D@$JJE`1L!JL)R}KP&dIO00@QR^1nNAL_^!)Myig8pyYtVsC z&tLUzbpMd~i1FicqHA;Ie)B*eloChWu_HCs3J8nRq3*@6j)xtyUiiH=3UU zACbd}GIzIM(0Di0^@_lH!(L;r(S=+8!+4%ylNY&9=TQB#0>Machm&El=8w*B_aeFL zz-sT>KsG$9ts1*`%YV;bWoSqI=JJBH2GB6*sVXUU6;jwKUAXDmj}MTDpT`Y!C4N5| zyTUXGK0-Wh9gO8{OQ|c>ckgGAf(PJ6!!6us4SQPoZiMug_uk{vP%1K800viej!>;E z*t!3bp-+40(vO9xk;l*tlS)S(dcACh zoh>TLdRtgU$a^^r?hUR=s7llTGxW@ZMf@JH9}&WB?*iRnj01&E46a%QJ|;B*OIS7}jWCrIIjd0AoiL(ZicZ#mX zyx^ormrWK$w`E1HEZ`qo?(L6I0Uj%{FkF*eETx$PCNMfR5a#lmKH1zaRqDiW-u5|% zj-6o*r;}dckQ5aLKk5@`?=lXX&u5pt9FFCBPx7=|Wh!-6kH_T5&Y#1%U}Gp3Olj5< zNYjqpCm@J6yh13f!s$`=?K?|SUbwSQmja>+N$Y`j`D9UfAl5~@Mxy$m)@oX2XrhI3 z>9>+2)9lD9M*U3P?zA6?i~($6)f7KDvYOd&+%3>T%W9H15x<;Esmh%myZ z?_C)xi5f6>CkDLwp@SDjwTY1DnxX|wzuod(f(m)S2^s809NsybgFd-YP&FfAWJDc7 zDgZCH@hwN=2%1vtDV9* zCF9-GIC(CH^)NO(f;Jis-hJaT?l-!s1!zx+2F)D=wwm2GGVJD3mvWDk=g?Eb3;p7T z+%rLGk4IcxhX?xH;U_zGSCB_%KiGGZzWl0*3~1<>LI}@sO-Y2N%l%_3*M+I72JhT% zl|7x=UdqnMls}F%DJ%HnJ(a?0` zOM2m_ui-tEs1!A6*~MmFHe=xpW=vsD#xl{emQkv%kjdE4gso|q$_0F>uF;{T5whi) zs$?BoBn{ZCXNljGW@Plw_28P4c8V|k#X0qv*NV;FMFtpxwKb$zTTSBsEm6;d_jdgB zN}hA9#*qfgpE%nR`)|>Iv?v8q=SjM8&xQbznZ74(!0`1(PX*xTo6(OGeQ{;YOA-u8ORHmi72jaT+kzTOo*bxzQFHQpDD6Oms zzhPLeB?HXVq%)rUpn`H0XQn}rq@7k(zEIcTQRIT5Bj3kA*oLg!JV6~JCy`234h34Jx#vm*L z08@z_3e%&kO(%w+11VkqR!}|0Q$*y3VjKM-XzCl+DeG3GGJ}q?E$s?SGk-x+FlFx ztz=ZC2K%#Y03AEF>w%-4JC`;b@QGuFzCCY92|_GmNa@CQcw2tWMBaUT;8&Wj#ti&n z$$4$37Q>`u&K$tTtT>a^42D&!e1wn}gcAmQng+V5Slc*%+9C{Hfe>2@zZ^4`O?P5h z41DnLrbSGC`7`GR)|1S@6l{wmGT*EK#KS{Z{G?dW=#Mb{F(B{xQn=sK+bd;VaKpd1 zCqpXYF;*0&^#ss&oYGt?$`hf|lx&0Sh_k_B%V1L+KpBOO#A`vxSiz0%9_x(``J6|( zPUut?#dYZdLAy7|;C@t<3rG^OK7A?&8#CrxBeqh8 zt;KJ?;Q(da-xZ?bQ?SvkSWm198W3+3!e8cmTLIwPj4@&AQ>85i3IM=K8TE3!x4FKf zSj5<}9nlys+sob^58_1>mm3(aQ)#R^*gM`wgr0ayeWjIdl9MIq`-oZ~$f|W!zV1Eu zFQgJ+81pYuCr4VUFj@WWaV!I1z)!gJfhRtX^LAV#cHZ0CIH&e&Ca&4WmHZPvFaKn- zU&gnfPWA;#9sHqXQ?v0Co>`+lZVKqz&Aww@`MI--$eVZxjAlIf^Lch=C&V{5U#q@B z1qM9)llyr3Qv7g$du+p5+{eBAbJB;-a*4BIz1;lhXYRj)Zxq5|GK)Jy0b9c(l*|xN ztdo_w_;A5-Tx4@nJ@9Avx*!Oni%OI)u;&ife!@ZAPqtOn&oD@MG2+13*qfhgPc-Zo#Td<`jEq1AU~CZL}MRZRLvA^!AB+lERLQQ z*WY$99X0@0@zGJuN8q0Jm6^T-Hm$eL$sMVSqtX0cgx5zoLdw@2t}aD_;2@EY+W26c z+x4Mq+Yk5W&f}(cT~}ZIbkXa_KNUS|$*7@;5>O3lG;jajG?YFvO1*nI!7vyCs0xW%j63=abAEzAwAF zn^AMn)Qyn#c%PMRRfI0GNP{*1JVwDGH;x2gMOanCkM4z4PNF>vei%lv*!-OrIr*1Z zmIwL?fFCuQJ`22bDYKXzq3{z3Tuj~UD&y$C@AHC6scez|D`trcqn-^wD|SYTgf?wP z(KvkVo&KU<(pJp>dC7Vm4zZ4q>TYpsnOC;+(=DHm9y}BPYt@`W)-WavJ#( z)zE_r=fn7dTv(1Xu#ygB*1xj`-8L=N{tkjQ3L|07jH-|#rwO0$d$RZlyMyKiC(i`t z7y-VOWjkoP$gzQCDB?XZ3}&=2thDV1+4EF$vhv9zaAqghBSrR*EJkDDkac7l82SrT z0o%QgYGmLN3Qaf2JEziE&wSh&Dz?+OZUauas%$6Iliy?z6>_cA#FH^AfW_YU^>l1P zi&T<@Jdrq(Q%T3m!;2WdkG^lqyLaULo1IG~YZQgja3!aZTi@N4ff#Nr9{7UYe%+%P zw=z$M=kWTW&Yq{g>IjWd@)|rcCzX?F11gt9|=vJ7`LpV%5a%;2tV9O8?Tg*J| zB9%PQ%WUy=dJ^M^>oxJ_o&#ah+|;zkl}caL={LSNoGVDK`TG1@joL#M{a;iWhCM>7 zMB$d}Ik0UT5+dTKO|0v-8fZpY3~67R9wFf@)?w-kqu7q$^%MSdqBgFWI*XNm)_t(c z6n?w9Nqpe2X9??ynDchCA%n&5QYmureWqKs_Iz@{mau!^K9C)HB^92C9?d~`^L&4& z`Djk@86ow(ao2bAmDb{KC9jHhTQ+>ZufsqXXN%3GuW-Mz_@sq$L=mYmw&`i7%{Ld| z$ym?Zna}1oIBjV`nropOL#iSP2?^N+M-&VqGr@rG>%|9U?!S^Pl^Bnty>TqMr(eNY z$?tXgbbl-onoESTxC*ZR>PBsj(kW3;#gsJH zlCH^g+|ULLKD!dcF(H{9SVQ+19W?@rpd7ym>;?vmdkk&Kq0HPN22I|m*KH;UQ8A)uLv2w&@VpqzCN3_KPW$KA~8 z@wq4`R(vqzG(SkC>a5c!G7JSnf7qeCf+mWVD<1Qy7@_bMo2?7y_c{i!s2^!qWV=dw=fAYlD_5W0Lf+qTo zho35JaAW8*D^O1nYXTlc*uA>7)I`v^|J6qDX5>BPvSrwmu20v9`g*MF%PtieL8J1^7jfz-D-s zti*>ZciN&(_EavlTv77wQ$e8!_ZSJk9~)^7b@RSek)>Qid%hJ8En8|YYa;F!eoY4R z9g_+G#%3w5m@2C{zMFha=LxJLXr!C3KI?0MiLHnppDIlku5^>R`~v7#vDDgU^2MAm zCR8OtfWnqtQOOybaV)-I7_MbBUzeKGlo-SbU)0|lI6u~Z8g(W&95A-l-7H^|17`F9 z-R%Qvu+uFIAv(};E*zj0fkjSM#T?sH$riL65rh?2#6oV1E51+g{H^waY|1mCAU%Sp zI)zrC806&hAJy3K8>lsLP1io=x@L?k@1(Ea?8dxm>_{{dY3=m$X-t~Y*{X|eK46|U zZ!6(+h)&7YGX}4@@NsK@$i*mi+wiLZPrmYh7hdzo10Z#( zjJ*w{FVUWWC+xuA-}w5DMhviY3bkUqg0e(&q26*I!A100a|Hr%C7!wjxpb&+56lev z@*5dvXZE!|Ts={pCBj=7XuaRIr{mQ}493HRl zc;%{&Iu_mn3dRq#XJ#vOFXZonv*HihYpZB`c@#SpVpzCxe94o!QQ|4Tfrq)|vD|Us zJG)QeYq#ReZT=hByhh$W{x8U;8ZnzI?4xG~R@;JDLLDnoU2N=lvy=G^o}&C8te8YK zjIQm+k2csSHThNy2(f`Omk-*==48N>X*B~KTJnV ztezvufOOs6_aN_vJJ-MKeFZ}~;*BtrvrPF>HsM#*$@=*j0)8fv$VXb;_8@k^PFZPc ze|92%hIf5KD(V0#Y?f41cU{Wf{6LO}e_ugAEP)aw7;hOfNb}yITK+d}&+%--L}HY( zpAi|7>mj_iqOHKnB{pEmQU3B)w)hAnEHcy{aBD~kfD4%o5eU#7jJ&_&{ep}ot;HMf zzO-t5SUUVhfrifhI-hV7$nfbS%P2OpC)0J0>mX1eQ;tCRHumLo3*#1G20M{?|yr9DQ8 zi@DLGPO%btkW_n^^sownOM8R8ZGOB`%=1)(*qFY(m6(#G{#!n%1C4%+o%#J#2ucNf zKP_^fgk)IS^FOAu8aHMPrfdG5&$_6DNF25VubpJh_AK(h_)>`ZG+64X$Ei3*`0MoS zaQBYfxBk&CHuf0j85EuUWMHx@ipLpoTlhv8Yxut;v)%xKh_ElIBAC!>Lg7bpesFr$ z{wJfw+0{z^1GwxQo+c&7)r+}=*_-pa3(j(O15z6OjfRz`uKC*Qc>XHU{_D?J6_9rC zmUzwzzGp6a2&49w69$(>9Vhca*eCPvv<8m!U(aj#-a{{4Dluv-SqwsPTigV~k}uH4 z^EqfxZvT9c5V^O>p83oE1_}j=*cO4Tvk8f4{tb1Pd<*uON2^VyWHqVa>>v{d*1o~U zdjM^rT=fgUQMC2{M;x^v#@x~rK`C|rb(I!mQl;LWa(^YW`BbDlrQX!R{&1q z*|{l)-=2#2GyIi$0!opBvzgbq5?}%lk6l%OF2zAL-V>#}!O|IRoQ?)&jYL=PNdJe* zAAx(1<3Bvc50=$_Td)|}4Awxv@*;6VCS2Ou4wN;yGo?^mPD55uQO+Q}UY2R|3S~38{weu9jQKuDimi<2l|^!tg!l z`P~Vkm_M@=+JG{FV^tt{N2XO!Xdj-qc6s=Co3C^f^?eG^@ND}AQRY5_!S&_E_uVCD z4n)$n;KQZ7;#K9Esj*$U+g-LBMjCnx2#bW>4jGX#h`sM|oBEU5VG@d|qUfi8ACV7! z`LZbSZJspJn9eEEs~s<(iI}&RV)2pAFu*!gVe5O2L)z+lQqz_VXcfppIZuWbny#-z zizjFB@Ji`3n=+o6-LPMZ?vS<$Al_TN#$XAViM;F!0Gg*#h|A{s@GEL=C;&~2ZWLy}JTRmC+1pt>Kru1Z_7R{_i7Ay14-r&J)-cUk1Q({`Rt z{R2%*XWQ>nO^Mi$C7! zsli{Wn3)WmOH&iIZMIhSK7eHcQ%0uJOH8+Lt$L4j%qR=q^aG%&-ug}Vb3UAv8leN-RDTir3#nMEp!?f5UpZy0YUNsEKuLiJWKXV~$Q;j?1>HaV9OarL zX5*X6VqsC_JD=!D?2`UnL#|_)Xy(&n(}qIO0{_G2y&D5wnkX>Lr`>>(t5_3$gGr6t z!hQ4haY)Jf{uWH{v|l2i|>DWTRbj@^t2T&`Gc)|B-#`sH7QU0Zt>eElr`aG-% z+(jcf(MywnN6t%U03C$~>{NOjEo+(se^*JF_fG47^U4)m7wpuJw12s z&Eld09(^X7V#?xhXlPc9&^+yKe-4SF=W$L5am?(reu+{Pa?TqBvk1q&wfrSFO zFtM-CP#3qiu2-iI#Q8?{&y1$#7rH4=EeZ0UuBgK?zbtRQjQk)|EkBq0A?Lc$S^yPn$oN_Yk zd6Y2dDo#svH>wV%%%iZB88yC&g(&~HBNx1d!ieBVrE)AEytRTZlEoIcQhY(uj5Db} zUC?nR=&-FNxG(7E*)P*YHT({m$YIOh+s9J?5N!}8hgC*W<4&3aXI|K3Lw4H~x) zh9Uv^AsHZmwc^#zbFXyEfz5ybTGh1TZmj2On53lBHn6w?oh{+=hSB76NiI(OJ$H0W(lMRhA&o4p-Jz3$J$XSG z-26~RtXdV|ZsWd#@wzhIgH>^7JBY`2CfO4AH}tfWoWr?)1)}CZ&?noG_m!aKwpMG+ zGk^<&C1M|C_s3#h3cSPe3^@9D*cQXLlxBgouDrdmwnpK@sePM(RoG>Z#Y%3*_-3eq zjd&^o`l#bmwOa8ypH@YFmXE6x7@TmJ&+;D6`%0NtC8D7XjQUqXL2c=5`(^)btJm|C zrLUj`xAlmw=+7hwHZ(YB(HwU-^nyD|)I~5|+>iQbcd7(Q%?L)R0c=ykOU7B}e2O%q zl{w4~sKW%(suv8BO0^J<@PNTNvOvr)@}LC}s3AYHP4j%^v+P+Wy)RfHV)j~B^iq1U z-pBDUe&0*+H((&sq5$Wl?B7F?TOCLCH_L>#qlBQQ%5h}TE*LfSH~N$@y7~Ino}+3> zYofNu><(Oqfid#dZ!K4;{QkxtIMlrwdF#u_NR9LE#bD|NMy2VK77?@kwwkBS46|n` ze0Pm2nWzXmAqfjJ!rHSvjo+Glf$f~pmpWz~NG1O+5v?#uf-shX3|#h``0)t=aGN{X z{8mh;mX`;=Z>rb7x6Svf-1w@NsR@PL0vDFyyT?IZ)&gP>Xi~Rk3|`{N$O|3$P{GLk zt@W_)jh-f2S2OvFtw3O=v|}^79*;`Hb8$AxXH>=TQzdUUDQLm3Ul^b4T%`O!uwlI6 zdPj11Affiz_y99-!t|U%6zmyqi&*S%GqP{G^WPioMu$FeKBP|A& zD^Y$noMYn=1&9+8jl&b5$QX0maNOcl#F3?d716&MUGc_~mY(8@u!*gHK^@lm<^k^b zt%Rl=Bne8t-I2G+t<7!w8_nfigtzx*)g`BfFifDbOge4&eM(qN0Y*9S@!$KpKyo`{ zl9XFpNPXf7NhgJ2ERC}E+wu=%g4eR4TL>Up62#+%8Bhy;_u*p!elI{=a2FW?)Xxkp zIVKo@nWKmQfQ+}`35p5`AkZK{weHhF$y|XD^0k{=$Nt|h%l#p51$ZT}UKlFyBV0mv z=`pMnDFCK#th1&}PYr@0HtnvWAR3c^{lCa>(`r|!tmCOFGdsLR7u3ejd4>v{#7ToGzzA7nItw>ec zDEeHR+4H?_f8D`u(2l-XgC$1+u&u$^Xk z;bUI-NN7KZdS$V<%PjigLMh~h#{Pa3pCU>XLz!v}=~!8l>t_AD`AmkGcnp)>R6okg zKQCdL&41hqixq7GSw4=<+99oCrBwm0O#Oqnn(dq7N?@oAIbj7|8gv`L`rT<%*`(Bd zW#HzP`I(%so#8CBP(U zK(t2#uzSEy*Fta2CxH*<1T=NG@;UHqzi$QJx_REdC04TmtR+Q&bgu`z$tOeNHtw3QuF)8zj0Qa!bXA(&)c1b!^O%#V&=Y@1fj|^YHk50dv~)Lt zdcD-kD|uq~p}d;6gj8Cv$buY3v-7#}Zf*tWV3;Ki4lV`UKV6fS&G zzD{|R>eg33y2^UexXtG(47};pxf8)Z%H#{7*5Di+;;em9d<57KC=*@W<|1Ojj+hx( zodz3ybcc#YKQaWwyuGv7iE{{)Fsp3RNQWE|?*zIb#9Cu2(VMO;e#W37tNfZ5qw#rZ1Oi*lsS^y|hEQW%NT;+#;B;Vz5&$eM}F`kV1Z-I1N`>?4*%;&tC}WAQ^8>FGA~&V`-bElE!&SZ1gx{F4 z`<*ijvZ_wlecl6Ny6}*Y?&52>QI5Z_us;lMeo_IJRRUhzPe{qQL9>47^R7_4EV$s* zVq|XhhVX=hoOQzHW&v5(W7Zl^Rh!ite$q7kS#e|tR`q78mqCbJN@X5 zf#N{5_)QdUsPN7eLh4OXQy2PHY%-7p ztzF%)jJ`SIIh0d0O2)|sY8C5uQwiMJ5mfbi-h8|%@@g$acJ1q=7e$UMy4=|d+Hd03 zhlw<%xv1|FOqZIVtL1CpsttmRK_kuJ1~?Fq+jHG2K9JbN)dC(B!HoN~IrkZ=R_4l_ zoxioTQOR>S47*_rGsEYC6YJ>9-dZ53N3EeTct32KIOJ4#&}Q$@bmwBAv3uUV!f$zb zwOO^>T?Wj&0P9o7HW~hC??%5%w~I9)*%^n*HF&#OMD9YJD8H}Y{T5!Zsv@^bM%tg& z1-y=3`@fgNuB$)m`ds$9b7SbiIupd(aSqW`1FOv~EgY6Ylj2jI%uJ`^ciE)`=(&ig zsVQC*9WOAj`cA%YeFfAXsIerapS+KdaMB}uI!HAf6STCpALn4Aoi`kU)H9>q@@Nv9 z7HAG3O9)7=Pb!YW)5mg~PaJB^>foh?z(ooYr9+Y7D2XM)%!Xnhbtt?}NS3+h%bl?p zBz+Hm<~n_LrT|zGmU!-!A}-?sYj}7kIs}=iNl^xYFffidWyx+uD` z&N#j4l2h;GWp*yNLZq4p2JI(mwJCH5_~NQoJTdFf`qk^-Zshs{3sM+u>2PRQVeF`` z_9S&W6=0S6+n}u#t(qwS&jTo|8HeRbqCS3%B;#m7gk(z@0x2=O%po=JKDr1(Yjms6 zgC?xcHyd&#*Iybu213k`O%9VKLvp8X>(I@?&(EY^H)~%w$_|rZr-O;<>3*R08bWHm zKf^Zrz5XJpUk~@(2{EOwY}ofCF@@n9T)ZLib`Awl(#mhQoLA(b`)dwLQtCQDDxuoc z#c?144e07nd13gd_vAA*>SHC(@6TtnL@{Fy)%n@s&#zy1T2cO3^J+t{6A5JYr0#q$ z!@iSRu=8?uX*3mvkz#i<)9%yCp$X09&hUy|3DP19J8r9N=DpV!JlPD=o$mYw6KtK7 ze*i>8wtxs-AuxdCv(Rz3{uE#_hsC$4`m84RHl4Rysrou|$Q>?m3wY;MCu*5rZpSY^ zL@G-{)c3TK9Uu7md%73pRub>#xsxp8wygj1jCm1at2c{G)Jsf|uTMlHH+(uDMQYF> z$_n?xnPgAXUf{57X~XMf<-Nj%iqrY}`VO(50fI+3&1o7aOxKKm?C^RZ ziE!Xeru~aD2dAgIKMAAC8vU66@tG%^z3gl4P^=4dH0Aj-i6p=mWWEbsNh9Y~9`WNV zEdiTQhwO83L8SZNon|t2@7NQiUSG*R6**`1)OC^8RR9-WT`BXmEJGX#gPs_=;LuPo zi~B5@Ki%eTj9n$J_uqqj_e$J5%`nrslX8Mi$EUnJX0>1>feWR7?!@(^l56l*77{EA znAyRFcKD8$nPmd0P2MC-mEa4rzhdgavZmbOR~?VW{A>UxRszQI4-zXDNoGI>-?INT z41cXZJ#IzoEhaUEiQ`rYaiXmef2+lc3*cIB0}qKVYeaD10day1kcoe;qB4PRK74nC z7aqK>+k;ONmZQ(GTkOPymSk00;X$NhLCjKteH&W9ei4zeUD>na_Y~ zipE#CDF$uY9r8!IGk^7TLta)iZ%VDB#9i2U$G>>HbR#SP7Bq*I(K@AH7RP zuQbZdMY0r<0;3zArENN9dXWENT{ATRqmy0xl_x18m%B&jwiZct+HsR@4reCVn?`DR zmptlM&id&-y0;#&D?|IacL2sw#1K#st8;RWLC?Zx(HpW@(YQMAb(hfs!m)fnI97G_ zABAJ17awkK0o2S|Q5e(bPlbXnu+0>6=`_5@?m_ziOt;EUt-3F~FE2edy;13*G{hXn znuJQge_%5~AOsY@fV4dY5|VUr5W6A<5PN_uow=cv4 z_=@vyS85;qkAtWBNp2!Yl`5;Hv4(*yZ-pDHWWz_|D$q4RxZ^op~|#7A-#$XSb|j~Y%bhtSAvMk`M%TEt-tP3W#z*|bnNPc zHFF>wuUs}pfu8D^c=gWb=(k>(x+$to%?}BlD{K>LRz}416@RErKlnV1Ogw9g(X2`%k&zZW}6 zc3XX*MLD*5;43r?pEsQQl@jx54Cy|3PO9ZMl8BKa%nz`IaLX822brY;oE3iiPF5H7 z*3tP6zY3tMFu_q1XjH!AY6)M3N`K<{o?pVf=+6_)P5_+X$jCLd|BXuF^Rb+sLC5YQ zQf`n15Fa?N*zpfZd;XVbvUK~&9iJR-@&H!}CS=T76u@Qav8(2TWi5&ffA*rrS0(Ry(%5 zZMxcGayzQUyF$4)=u(4w({yv9ujN5;m*(|ex0Qo~c$*EW$BLr4)Ni9RrSS=vbr|-F zFf?jXPc7`hzea`S9`UBn$KBp<7pW0l946K44J+ESUA?;v`YJq+#Frz==YYO4SLtcS z*LDMFu8(H#KWkkzi<@H`AQg1mhD|=L+Zd!3C=wXzNSr8DfB8X#{MH}Mo5?pUhsU`{3=sV$`c=)OIXV;{ z8AC5|Zbm9W-{V}6PCECZfOwy@oi5u**T3D#@K7~HYZ4b4<9 zV#FZ1it-9_H+pd|5tsK7`Uxgt;@1#(WD+6YgS=^TUtG86zO`TV+n2Y+p8MgRC?x*U z_rO~QDQ2%(nDr5k0+7cXG0KaiNTHBeOcfsv{2>FgTVz8WB#mUV* z+(Zufo1+r`1fb(Z9W2_RM1Y{^9N&j-L^w2(t3#x)L!OVGqMK|R+AkcYzc%P*-)$D| z`^;x@d)Lu!yKGdnedt7f$fMh0tchL4pO{!U_r%yw-(4=Zvu8`-baQ&z9Nzmshd7!E z^T%~^5{d5B5fnb?GOG$D>-WK7nvrzNSY$ZyYib5ED~#IL%y$uXeaPAX{++cA|IhfK zoSLSLhDXm%#?b@PEL>8J4x&V;f>?CIg*w0Lve==&z@YmRo3B#<#~U1s5BL{?(OKf- z$S@+GnK#4J;QtB^&%fy~uOEX*9ko>CjSjk$zybc62pQ*TfY~P24zrr`o-r|#=v2;H zeQlN>sVF=V3-S+XIOrV?tPWbC&k-^HzBO$l#aFlEKxY9ZLUa&AJSQb!6F0%F`J?WoqY> zyf01;@zv&C{Z0n_75|0A_a<8B3VM<6QDvm%1eo-_@UY~32Swk?g)V24`!6N52{Zfl zPcsizl#9@NtnisOhAT^YgYFsA`qT3c4B*rH@ft8q_#Ocki2V}Amz1tO{a>irmK@iWUXu>|fSxBqP79!X*s2d~Fl^vqb};f%+e3Y_$i zKW+aWMU>3TzeqV~ajTWk`;9E}}>mWToAUvC>$O@YxhqZTgC@uAaqPO>w-%|StCwjK_p%)`9fKHLG;dAB9*&OZB{#-WyTSoUz5V^t7d|>i z#37zvIWYmlrp>XYFRo9U9kz-Wt5+rfZ!4I}RQO7vO}J&^CB`Vv0H`FnJ^qWBl;K^) zmLp_paP4qCB_?5b&~)y?vYcL`kH8pqvijR_SOMW zwe8;M&|T6Uq9_Q0bR#K>gp@Rhlr)IMFr~kIr~6;M zAkF3;x|)0Ii+i;m1q*bs?U2dac0{YbkKc`-l{JNmk_w@+ztdIGEtfXriv7TP`&jdEl`(EjkY1AefY3O71kI_%n@NppOE9g>dxw= z{?EPLM`VC^#_6 zwv;HXzp~hv>O~xAqk2bcT z<@)N)aH?h6cULpQ(4U+hzU&jN>3MS)Ip_HR?LA5B(nG$;L&-r?a>%(hf zkxbbT{Da7jw5{2;pkTM+?%$|Zy3UENw~si7`5&ARY?t?hu*&Ti?_P7mDXONnT7-uu$WbJ~3@ ze6{tSEiS%{z3@yV-91NT?;=k5XI^Z(Y+hDP`kvo&-aWZ>ttAA;_oV1wHzVr6^+-eM z3>zlr-omO3bVqRo3ZWlqd1dyI{F@8%4RuMPRP1T#G9vNC)C(psA>DpGlS_U5sc_ok zeGiO+nf4UVfK>eq`AC1-QXkfpZ8NNZ0<%PCsZz9*=IPuGGqBlss}G3pr{gKs&es!T zZ3kTSdziSjEXpP~GA}OOjlriDLN&lklHF29(2S1n`vw}DUNWeEK1(gNkqTS9*+}xh zy6eoO$ktS})ZBgdSu8#9@*Cyc0r<9Q#5h40BVH<_9r<+xoVkB=lV7S1`wlu-RE4^U zj~UiBo=KC10Q$x6bb~E4i!CzYkv=5B4P^U1j&d1?y7_~xRWj%0mPW{XI5*Y|okncX z35XG}L;FB=)AUj+E7u_sfHl8nW;&oKJ zi!>9Mm+kO9dUo@w-aEsl2y!}`qt7qqLB}FWxP9=h`S}LH7_LOd-<0=PI$X(ubQjo{ zo`G~}{=Jls4y;HqYa_DXe<`JC^brQMBjbW~X0}vx*`9rL^>Qsjt;v#%+&nivco#w! z*5yTO37riPOJ*5OkbFjum#vE8XXtfode7a2+%=~Y@r|+7@VK)|v=rmcHw%}K3f{C} z+nJtT%NFo-o{UuG9erv~Ix{&kY$xEcF?4|+-Q6&Dt;e@v z2v{SqU*g4npfC%aOZDbVeg9Uw6t>|BhDk6!4}WevDq8xa?4)_J7n#7sl(@NcWVc;T zWxNV`gKqG<18HHc!}tS->Dr2(K)vN83`2D5g`&dDcz}&Kl<^lhbt$OxARlDj2W|~+ zzI*Z-xjIxgG#nURi}xFZn-}v7(1V6W8KMrvHA`bE+UQ(*j(E@SEOFu#Oiz|g4s=b@rl7&_nd#`;AiD3^g8Iennvl(hQyI9MNGG_y zQ!}X3ASAzJ@HP;;&hcX7EP9cd97xm(Z_->LR9dJl$uFJEqek0;wnkV9vw91OE6dsbpk-%+2C_IAy=t6zm;sxBdo6R%4ikiw2}4<8|G)1c$A zsqo{#TQ&RyE+lIw&q4g3tI(I1ki`h_dMks4ZAb_J{TU+g+WKLJw7N* z=S))|u{cr~TQ1Ic3Jjs~#U-V;x*;N%>(p*++epq>yB_sW_6dW;b~*ZROuzl7fy%KF z^twM>f9e=;d?Azz8y8&a9;l`#c+^I%qvQR+gqkIl0g-`2)U^I8h#Vp?L&aIH>mgHJ zvcMFuH1A`@lbAFf*SRIb-u4@8pm+DdnUq1szG;eTfLTC)xP7yFazYVO$E(;pCu_$? z8JCX-%hEC)P!E;!|9OhnWhiOJZUo50heL#)Q>M{l$& zjc=Gj9QJ%|gk;`x~bV?SH3 zsEHBJzBp~ycYz`9{$xJD9qpC>DIK%X{n4d26~|@@hpr2bY12i)T!o+Kw|+N6m?*lT zfPZbtYPP_HRgh>^Dd$CzH4qrNowtffy5BB=o(aCtU~rw^gN4s%k=k{u89Q=^sB67x zAGa)q-lt>7_Ir@mT3jmM0;n2p-*tA}X(%CXTJCPw6tt&d63iwqzfzdW@p+%%Mk>I? zcM&VTPIzO+b6%zKDB)J`IW>#@M5HL$E5H}k>QyLIs11PsG3m>0wVAc6=55--sU==<_@N zV3HzTiF6LaOT4=efJFUJ&xqgfO^0JSPN6cKNYPpd9)C$5ow0Z*?So%lll3rQXk?P8 zcJjEg+<)>F*iil#ocu6vV6Z3gj}!sD?RM5bpylWu#t=cRn)Nlf=>JNyE1W&i62pB0 z<-@FkMs=ZpPGOYnKtuVyA`lG}`OxutcHjhX6MJ8!uY_@VPyi6L${1Np;AkJxtx7lA zLjsMVtd2UMVPLD$qzeF*fezSYB@Q4Bh_b^nu+{@*FgADV;(n4TC{YQN(qKg04QUJm&&cf|iT_4Vj2h5xV{GmykxCT^p|NSvm$$kw%kOi{uU^|8XsABu!5{@GtrQf~7|f8(xn= z4p8Ms^d7G7JDz|~a2p%^{(}@5Y^Jn`2S{f#fFRN=-CvhhiwkY{P!B~#D+q6-mMjAL z>Zc;B4;B57Nqh=<>hLK(1;*c3S1x56rR!vROBXgV>KBqx@R$PPDYB0eC*V5q4U60e zMUNuY$8J491`go3p#_iuT|5h`Y9A!f%Yoh0`Ay*ks7{}dF0J|p#KrZveG1|jvry5p$a&>Z11Z?4o+{}eHQCVNBtkr&|AFor62|_A z_j1wu4)WX+d_}- z5jZjb*J=3byTI$N@9@vRjm4zQ7D%oe5E`t1p~iij$(zLOthjb`?>zb@*N)0R@r1&yClJ zs;eIt_PEk>Zdso1->~;I17oF24HL;>bQBY@=KD^mU;zF|{*|BDbxzGdoZp3*_{6L8 z2!Q|m2g3>Dky;kknt^01CPrCi`_&qwUaxwlE zm}0LZ33)LYa8={V94AGFhKDTxoF1LT>-<_(x%rphE7M5>7;9G^z54WS38zC|%e^cK z81Q_e)M|5XktHDMkpSgdcuh+T%UTMH|JJ_E`q{b!cQday;Ha`ol?FyUNjrGKAp@z; zbG~t#8#DKB&CZAbAS0?S!8;d&pLYVLkQnF9r@s%*_h0CSE-tu2CuhxCzv*WLF{+9k zZ4|;J?xXy81(mRHcs`YzX0)C?R|>TTHanT*zyqj&z2F0vXNivE6K6qo3=W4#U&mgK zp?UW;K(a~B{p8%PjHNar=|eL*-HGwu`pT)8VIM>McmU(loA&*l7vp!Mu-Gsbbs-ip zOxmdMV{9W=4dN`_rwX|p)w+ZU;y&K4wup=6UqHzq?SZA9X@;iElR$j5ocEDmhRKn~ zg-PT>xf|fP(72aa`m6fa9W$xkQbbR0E&9Z1;-GP${x6!^WkIFtv{SV@YRtD9g}PIU zCX|~(8Yre}$7BQ23CD7&(m`+awQiW#@n0cHWXKWh%F zN0_h@1?7&&vgfC8iN9h_k&%U3w64O;U;IzGlU$CETBA98z`rsl+{nLl{If`(k_7mz zan>yS-2&(^!hadc($rwh^6s|P+#scpt_>DA_-Mw1;8@0MvL?e2FqCmazUTIa7+&1N zvH2-1J?Ga6jxL=a1H5H)bOWynPMo_B7|FxJv;j39!KbTy zjR8{VcmWDPZ~reGro7K18cYW?;g}Fm47B)w<`M%?q3+;@Um}6d{3j+Z!J z5s(v<(8!RABzR*q$BU_KWz&pJ`F($>(#;=uqgh5z{;O>5x^g3)`Ks_&&HD>GMhDE! z6QPH0X>EvullhZdoneLlbIO)U&1UmiBK|ViJa1QKp;6CfsFuI1{_JPmq43VQE~^x1 z>zs+8jveo0#vczE9o)aZwbx^EEkOWQB$EK>Pn^ z!d982d7ZFX?S4BOL21sMtieUuuIzuGTvZ(#3{Y7%3I7tInwj%B6vyL#L$k39$mowu zFmfsfz@ZX#7kSM-nH!MVN*Z8mwZ{)M0|u{_9_W^li1tOe2pV9$=a!N4^OHdvbJTpn zW?cd_cNKy-b?^AS$$aT9voD(51UT&hu%E54zcg2kACte8zrN<((m8n!quVY37|NWoX2bW`)hhnaxnG~dKXN}q zspjJqxYL10VO9R_r}*=7QDFG$F)ZO8Ub1-T$Eg5H1*vgyH}o=v-^UPMD?m*j|2sXr zP}&n+NLr_j#ai^BY!Ok#9D|7;^)q`of4`h1E2(7nuwS zJRrWm^TPmdbcs;$h@T<4QJc1Mv^QPSb*X~_z~}((S_(3tIY1-%h#VL`s?av&W!@>? z|7S_NgZRn12r$XX*T~Du;WK>?Ezw=dtsVtspE_0`MX}NvY1tf(j z=m&RxExk3(zXOQ+YN(RqN=*@N65T)M#)BZtJ+x=dVoZc4)$v|wsg*SRy$mB zC0a2(Bpl2%{PB+&P&E;MQU*?M(oG2`3U%awwv0Uu16bFh?{^ohutvt3rZ@8Oujf60 ztp4(0nCqJrHDl=mo1ajjg_cDKMME~zK+4DJ2_3@ptgV>xc0*}1exMQmQa#MbEaYv^ zMgOGs%)}Jfgg&6_Baq6XGhAhMYh+mUlcPC-Wu_PE#>cGg1Js=Lh?ZEt&Ab0r%N>fT zB>bmP{*+$$okM03W-QArm*oLPwR2t4P_@pM_o`_3gE{Ui64*uIo0d>IQN}!#Tl4K7 z14p&-12YC_7GCeuOYMeD_mGJVdd&_as?I(7;Lpfs;C$SknT?{7B5#O$rRRcRr<~_$ zQo$^CM6Tzq-u0{|h}KKgj)DfLrN0#g8QbOc^T{L#eyowTIyNrmD2Au7u6n4GF{JPh z%Jwgo4)jz~1!zz9{_%iLVwO|SeBX?}%YS3dwn>;9ofO>O?7R1LH}ioK6cDIDm_;=A z<}kWurh7ipdWrubbgK9-W>U{dK2O~2O(Jun2vO2qY4rB^@o(h3me~LM#PjFU@AxxX zz$bG}`H9TTN!VKq6p6KLZvWY4q%pma_V!_HS{Ua#)=ThyL5^9IxXB9kK0h?us z{_+L}^jF&g9#8REE<_UmzfcXHu&?&=qZF3cbi$jXf>4Ds`$$&=80z2ORsHry71cv;rf2KG%?1`)KvGMfZ zHgYMbw~ z18I3#``Viog-dx`t%=gvw-gYM2P_Y(pZr!0zw*TbGKf~7`x2^iYktUib$4t*?tC>~ZzaQ(uyixp)i0i```_toBCfJl??LtW=gVM$5GTeogq+fjU~bO|br zMSfy3M=p4#@LOQ|orHYf@JtDP<$xN-R!iZ>p!7TV#?)~+Eo63K=2)t{uz+%?X}9lt zGrJh=Xa;)pGiux|+uS(ImWcWFf(d$Lf>Qv(e<|E@M{Y%U`@NSTe11DeG z_jZZ3dSJtN{prC%>P(0X#v(*O3^iph7IH#uP#RFOaEEi<{%5Ia^n6BLK*5U7!Eq^u zhTPtZkhE_bJxL8>BmRfz8aZaPd{nDdeWU=~SuX8KtbLDwrZ|?)|DvbiNHk>0jWrG2 zk>XH;hi%zW#i(g(7^`2nxcds)-kY175H5?7g8J^O`ku~*d2LsW4w)D}yO!h$Y9GkM z0Kx8@(SckRURRW=Ux`yhqRPd=y3>2QGG4M_gCYt<^~l!1l)&a17#@@$AXO16-$M(J>fxXg#GA z5Syj6#D{FCVNPjye>X9U$BNoB6SXPpq_5y3zUM6S4M=IgZ-(*6Ky@-IElzW_EPV|q z(sM?@x@lQ4BSjo2bEe3s(`Jg!)sk0>a53)`+?dk7k5Sws-CTc_(2CPwzjbjO+ zF>cixrjR4u>qoxaYu~%NKwMxJm%`4uzi1v85CUCz5}5xYfp|8R955Rc$20U6{5-PD ze4}oNZ@e3i?FnT%xECm~ayHfoEEHK}yzlty2-sJg$FNF^t zp^%F0w_A(x`EdzTFlQi-sK-kpqVzN91Q`x_gA?6My5v@JmN*stjbdaXq+i^>1$JsC zTlQ@h>t#2TrIWQNN*g|Z$As_bxKk{{#M8uN$Q*yYF*N`ilRULc1M2ExlE#*VGit6- zH2w&7u?%^-?4S`6>mN)&>4)c>UtXLIQa_-8rEi?0-c^H`1w*=pZzjBz( zBK4LDzd&FGyxO{Z#nQS&Tl@;;4Ros3-sE(vQU5E1)XV=5AtX?%fZV^lb;};{v4FZr zXUGKJ(PU+%=?S=w=~A!7(xK#>?N^CbiYOtOVFy(j^AoFxPJ?1o26z1(Q68Y7zog2iQcExtnG;mOS65W+E6`|@{OC7$6Qqqn&WQD{It^M-#`(U$CIz-q%1 zwF2o#utAK_&NQ8%H(_8!=QUi)6>n@ewm1(7bd5|v%%Y@+>HPQMWl zy&W#Ruute7k_+jf>w5o}(jW^@_Xs<{FHif5H!B{xUu5(E_tK&YWvt`A#-(~?S;9aZ z{OZsAy!v^%w^-L!)wnf^W%IYVDY|j^^!#u=IG#(RAQD+*Qbz+SbDEa$NYt>lzWvG` zDViG#ba=X@kqg z&|Qy2*1sWD@;7g5K)cZxz<$RyKy|3v4=J&+u`#6UNB5TwK4CO~GQEx+rrVfEQEXos z{>H|CUOy-6K(EcLPaKXpBs_y}Yk@ch_>uql2UPf!Q;{Q-&yP`1|8A@?T}S``4by4d zud-n2XS$@i>4w~R#>I7>2sS(UR1Z^{9pSWIZN+4q5o`K%O)m*=8RiWtzID)r#S*C^ zHvAMAOF)4=bXx56eDD-a@R=^7ApI)dvCf^;#dB@*>KizwTHa&JZ4|2^x-?h5;HIeY z9P0o-5Ee`f3RwG0_BrF4{{?ax&BUHfG5lAFv7iL~6dYM1Yc$Ox<}_rUZ>e3Lnwp0U zPwYR3@}Xj%*rRb^#d^<^^IGr7!|$MjhG(y8=RoFivtUr`7x8dqadp=G4?M8|5)oZA zIXn95R*l=n#^4HEF(&a-uzL)V!WuiWVba9*ML$P){&uZL88tMZP-1ZyjIF)*5S>YD zX=-9iPTi@XM#HW?J^8`Pwm|ZIr3dQ`6&0Jm`#ZBFLUiDe|MtGZ@VmAHXbalAvf?lA z%5Yo|Q{X`Y24t{pu_Ru}#dKGA2q5jZ#k$U|v1^e3fj75|XM1tWT>)j2Z}Y>hL1=cI86m|ZPs zO0+qOhjyvS?l4nKx67O<-=+xtJ;0o-)j8ZB)R6skeza+Xts6oPD2TM?W%x~Gl?a|X z3YM{rYZrv6+k_c4-kYn$lBfFsGp^xn2Hc!+-acx>gu_ARYGy1y)Xxk}Mtz|`=mZ>r zzwVqkOkc6{6&^bvi>jG`*7U!rTWwz7pJT9*_G4if=c{Drefbx83ms+v6e-1Y)*7AD z!$FM?fHyXPOEc3PX0%1tHC{;ip0DTq2{quE$(+PKs#mPk2>3?!P2eugQ}5x4psUwG z1d_fUJ32%(oIJtM{Uq%DV{Bf4toZeIQ*j9(s**Jc-{VNLv-OipI(R7#5+rVwK5A`O zAj9kRJxVN%L>Ctd!W=`|!pHicIZEjBT#*6IFHO`pZN_8u4Ty>&E;1;`1z5W1Q3}E# z+68_+2VB+iT&MaMWDOu~f3rlfoCO*KoMT9i(;6_qfy>?cqQ(sHO@_pDoUPf}P;)?m zF-gj-vdG{3I?%HMxNWSYzcEHG25+!Iswe=vV+C2G86ULUbaez^JbkcFgY}elV@LsD zKq4!-@D<}o=Q;##wyD4T@#jr80C%bz#|a?$=7Py&nl8@{_U6M_&oPT}aB$um{vN2_ z{oWLkyo~z1dsQSe@q}*h+dZN?+;`+229o5=bmR}_Fmo~sGu;Nj`W`jOez>=@@k0_f z2zh(R5ZrgZw+eaV)_*numeNM*HLI~|N&*Dy9%4%H=SqGu>-aN|(M_|qaRO0s0w7cO zqgNdlmroH*tN33I;dKE~?H@)So1@F);o(03Rt=91#^?p2QFcj=#|hvA0Z_M@%&%xQ z661TS)M8Ge04G6w>aOC0+}w@1<1gQ17@UG8O{teEWtg9ptCb<_wZEVrIbY$?zm*Np zB6t8-IA>zaU&PEbZ5@ZEQ+H{^L7%FL}8%CA)q!dq?u zCghp;v%EPk{c37~n3MJ6u#yQBjg4iDS;Ps+Uwiz}7B~T|{yze({w#%%FHZnlw?BVI zuZ&l44qae*^n zvW>VTh9R77=Go+|{fRR6O(W&p_D zn;K|Oa)4yp7EpDCN981YeZn|J0Q$XXImu06@7N%2J6r}7mY|jxaUo1X0J+;6qM-ixz>NZ5Y4W-&f9Wp~vq=s#&9&;L=oFuBfBroGcx<+O96;+E(*!F$o!dGwENEwtK;<-|3 z$wj+0`cFv;o|syPVqk>ror$eN#Sj@MkX44GUz;#z3znrDpqLv}j&?2e)HogQ@dC1c zN|I4f9I>24<~WT;e#dV9a)xRsY>7FtQcrQye<4u$0`l=Pj=MQ7wk3gKOhn)3!f^jv zizfOyjEyJ21^f`LRS$eaMwuG&$K>`MUS1_VJsQ1I(`f{KNsxJS9Ht=Cn==Y{)(tjy zmNG~()=C1 ztbQyN`wq?gq=It(e)s)oAGJ9=iSt^CTrDN}Zi`k=(Y1s*M;2_LQLDp`Lv>)Aq?&<* zoSh>(lN=Dn3h}lM&%($r2y9KmjAWA|zxRlON7Ix#QySD160y&HmaHr6BKNj=)aYrd zvCGE;sr!oT99g?us)_lo;pvq`yT4Ni%k619(=IKTuAfuOY`q=-B`S`SfKkLjPC)_d z`}gnf6B52SXHnF=Hpy!>tEuDT$9o(xb^rdi=E|C9;|dyzD^fS34j!;e6wD_~q1Lvi zV3M3R^dplFV-dg5f@f8))6r4KeDm;7c-!sd4Lpy4ezumJiLv37SD}TBcr$pIaFMf^QiK5l@*O?1UT|k&&M&a zM~m65l7~u)4a#L-7AmADR=G*%+O6~thb=6u{Y0P-cvzWK_R@P+g9;e)u`R^*_0(E} zvn~yg)3^nLpAOQP1&?{#@5_>2Iwxz=klK^C@hWZ~SXx{*8&%gu`m4;4%C|tCU%;(} zuHNvN&N5$~9sMw?j&DTZ@gI`O%3WR=HS)Eb-a6eQ%skEUbb0KF!Y;TuH_?Llyb^d@ zjj(?fjK6>)Yc6_7p1XLc;U;ickzvtIKkH~aN7U6lVo+|4!))s@i1_WZ3BEp4`?skw zB(WOHtP5l4y}GHUV8=oHOtHn?ZTI)vHwrH|q%wT#6C{mif9T`qzVlL*H52U}W%ai| zNx-Yl-K!DYO{gJZo$y?ctaN+IFRW>zaVn{C=i&B_A0AYOhl|6MoDJV{PmLUMYn^b$ z#4KiY`>3zfCZgWIUrQY&jtoFq(!uqq7PY>}7k1oF9g2^fR)9u-8DsD_0)HgR&F>861nfvr% zjP4ZNpA18cb?yON7@(QU0Wa)*nZR8rnK;dTB84*S$4#L;cYv^z_*~k5xWQks-C76b zeG=gMf-2xm+7ZPtfzIeB>_NrniCY#YCjugt3{Zk&obL;^-D~ZmtoVz`=D*~*wo3Ka z3UQ-cp0_r+;n={}x`O%#{pO!Y9I(W}P)O6?uRIF9relJ&S)1eb(oq?d`Ms%v45(CxJEs5^1>{q{gQn&$T}Z93jGi}3k&Xg`17IRy|3X{llG5LS0^8?kO<3X z9^5jhon+VILi3xTrniNmucD+f@1Hn#fKf4r2!B>>lqQJ~lH{)JDaJq}3c}g2+Q7an z(s=ZV0%*Rj6Nd_6=tqBpK6pqMmOG^r?!TK6z42z)7L>{$@Kd8MbHtn>a%7{k$yf8LoU?tZ9*MN>tw8$F3X#n3E7F%sk@Bw<{Zl4z5c*#7G%R!8CJc|~3Cf>^*T z8$Bw40;egYDl*1AmeZT1@kCQPXa_o&?!L+*DC3EHbrQ(k4B}-6=^~zPg1A zNxf;ab90}}T5oN;xR0p1Y$<)rs?n@iTu9&nSP@7oQ)0Ffg_Yho`?ON>{B z-&V7+3=hNcbigcFu**Y@J@105VrvqNmBHBc9a_H2;`<4($&&N0jYdZ&?vC>(E({qK zYglAW!-t{(7$P84XSn9vAQ-)5>zV3Ea2mHRThHV?VEFO+i_JK4!}pJyPt&dB)~j6C z!oMVRHIGD?Ow57<@ms`%ASd3&ya&)Kexx1KCBx;+N&Xd9E(|B_>h~xcN=(Zr`Dzjw zux|ps@b+h|F)=!o9*W{U_;HdTZN7GxPPj;ub-XDTb#ac`cCJ2e!m@Qd|Fn9w@k+*w zPZp`|ONtQRL>QRa>z5*)S*;=_XBnmrEo%{ugl55Nw+G3NLV&YyX%cW1XkBrsbGzjd zYN8&)ls5IP)t~%+9_@%H3Sf3u znR%-l^D~t3ixaNKK=%_c_9tdbncvb6s(_BveP1s~fY^3miZ4?p_Zp9h_^nd;FZ(bq zox%557zSfbVihkkN_mxGBfl5Fxj1n=pu}A?{-xz02dEz6YlR;Sa=1ek` zGe*w3QfjrOrgeV8n?-(y`0{j9HH8CHjw<(MYWtd3RfuObbn+zkcT3ey(k|F2orIvpi`iy>gnq942UCx_5OfHgx63Q*i(51UM**uioSb ztFxcZDw0JFqvYcSRMQXDz$%XWQCp>Rw00PkvU5>h*T{-lY9XQCC`7P8<`=r>kK}nF zTOW`_dqp~0$iu%sr|Y{ncJH;XUSNKg+oZdOvYc@vkpk9XBvgMCOVmn@{kom{EQ=GH9Pz=c#5miho27~ z)3!@SYJnfX9wrm8j&&AZ%o62}2V^RC+7k@3rW z7hSA0xVs!3fHsds`YY#TW3TMoV6;Bb8B#Uo@wy(zcKu*-L=S_{h zy2C%S`oIms(+O=D_&0*xt1lapT?)3z9-&TVn-81u!ehYr6p7B3KgY}I_L}kNguS?X zd1m9+gUQS#IL*X7*`C3AS=l6ZHmj-T8%jWZ&@;M{j0^JY*x!^yEw7E$3Yw%hJuNkT z_)0{)Cy7q17Y@7ce_kvfecva-XagGxeLE`C>OsW+eSvNwI0c^Ps_iOsj;$8fD-T32 zTl??mkShrO{m1uuFHGt#Oh-&bUsvE-q`?K8{a_WF2VXFF?^RKt!@R7?P2*p8#lhb; zq_{EYNcsbu%(TS|HSLS&#eOtU#~on%ZFx_@NLGzO-M>#mgpDr5ye8{;rW@ACm#?ah1AT2t3e5u<$=NHYb?F=uXt0Q!Lui`W2`ZW9_f(xR= zR3~CT4C4yrb;a(RBHj3mciLZJ9meZg4j6SFboIJdFFV_%;*{hzHqWhousxbd!V?}Z z#duv4iow@(F27ONKs}sDhXJyckGi3Tjah24ct|g1(Nc{KQKI#b*r&mi+YG^dG;mjl z#T_%=x``A2{TFSq<4K#{dBkioqD!@lA9cpc{=4rNYS1#edg73NM~`>2pr5T&T!gs? z7jeRdKj?b5fvhNkKqXQH_&b@Xy(whZ}__ixR9Egj6V zC98Sb5uI+GZQfN(d1KwjW@eH>2@76^BnZpkKd<$_1ftjyEiP2D2^%H8Fc_F%>0jO5i;(LI-zS z$};f~+FbOz3tuN<^{llF&xtB$b)z6k99rs9~-EN0n~#3V-5BJz(=(1xHJ4OGOa z{M%P*APErcp6-Iie{uI}jb|4p{-*34&>xpIn_OCc->ThS5HnbuR)Aq|gYBj0$|m)6 ziUw?CKQ(B5^}wfKeRKwIsrv~9(aLZ3qH1q~vbAz>U6v%gL6{H3F))}A^h2O5lY})% z)O+G}j>UzY&IS?s|MUL%@CzKbM<-;K*T2M5b<4HqJlXz%bw|aI?l@*>*0Ci8O#-w{KWtH3ai1SXB9rKOdNs{J&R;0 zx!OLNkn;|xC^U+jKg|3Yw@M?Nz8G2v5JTgz?c^)%JCjGW8j75HN zsF_aJmFWX0per2abN^N2@vW%SL7ym@O&ALEC{n4*_hu;f#aBYl*+`-Sq%MZJ?V!2w z^IDyCN$L+K+wneUbXj=t=65-<&EozdJLiL}Q-6NEinq$KYbj!8itY zVsHs@+7?1aA?+LUJ&&vJfjhiVSk6Nc6=j%THBB1R=7$t+bcp5~y!Z+cvnJK$I_ z8Lq%XH(}$pzH97at9k4jWU>Kg5b*$@f`SgBvc;tRWzyQ<@AvaW(pay=7f5SwuGp~W z`)LTZnY=%7kOt%TyPCDHYH%+DgUS2*gW~*>?S^DN#1IURlah|xe4^5u&{#6iSb<* zK-XChV+nHi!+zm^NSdXi@n~(7+z4zSxw0j~dHI=uR(LeNCGkBJx`XmuVCHaJmw;$# zIyw00nNfYm*5=crN|`UC%~tcazXO!#Kw{~EqA`Z$)+8Wv0C;!K9jg>c^BHC;sqR}( z06yug(+rKP(O#PSCd zJMY14f-yB-o*tW)Yf2=$u$jSCT#gfy%a#+4eQ*nIX6;fWP2wvmzFq$A^ls^1tIwnl zuHkj7K|cKTE24;5!O!L%p|Dp?_+i3_d3#SBybgLWQ)a-+m3X2G>&7igZ5x%C8@}m*{^2B_b6)Btc zCWiPu~m&~Y@LHG-ymvX=~llF}ar}6T+8Fg8VQ#!vB`>Tx6 zox&~MXjNISu8S=0EEyW0q`%yiYzdV3#%kQTO#P8Zd{`wPo{XLmr=9bt(0ZUNxGiec zkD2&at>m!h3d$^jdT^}f6BxC(bp>0G1mhteG1^<>QHX!qu6bma{Gc*0FnHeJbL2Ro zC#R@O}5$lTQb)>kc0W(+$yCD38{uHRz4n)8UgC8aU{#gs%- za@#9B^Iql3@eq^AVMhFF##0uJxU~E?pp{=cY{itrq!f3@IWmbRB)UdgP3MDb@psaI z`&c_Bf4ld{=bWV5-xN|5s!GmA2bBxWy(IafaeT$5n^JG6o%})ERD0*j*K;LS;)sMg z=zVxdEG*htow&jMT5EHcGO1bbA-SfeW&jQmO(rn+fOsShzSRp`3VM=IE=xr8V2)eM z)K*tFhVW%(W*K=%q*8T4x1MUj&!ii8-QN4z$jJF!2SAK6aqLAY=m8<%+Pr*oHVdlu z~DhLB0pfXD_o>Dsw>yJc$-9)Z(gWBN)=> z=&ylcYwDa|^71@m+DKfwlJ6q`_5iTEW{ekHb@nTzvpp~S!cWNu7U)b1Ts>CdUw)w! z7;d8U_&v}A&yN*LSBHFPOBJ>UfdHQEu)g;_!youZM-#3Ki%-YuJWF%$QFTKbbEMM#-HxBx@Xzv(x(gczOc z+(OAud{M|h|K;CuSC#xNvD#Vh13H=6fN5G-kU=(MzYu}#FUo7YJ_xyaw+1>QFkken4vU5>xF@xo^ZS^!fesA)7on;?( zw1_74Dr$S&b9-iq0eU*@mf^aN3Ps$pGPU`(*x=s+?s=9cFpa$Khxl;c6Ew2vNu_?B zIsCMd%ieise1g($oPK5-*OwfdXn)$^EA%ESO<-&Xuo$&Y2%yBn%EscQR3aHlg?UO? zhMzE^Si)>UO)^4$PCs|W1<5^%u%l_ENRT()-t)Db7ju|BB)K$S)IME(x*0f*iU<+F z>}Bzz9rlFFoj-D({BepL^E=gP^83EtLBCgGeDd3m?pa3D>xWGr6;QOO`ri@E$;)$F zWFj<PYorUZn_9Ud-+K2xe^4*^90poLbI1)|@P zHlCLwCnZ7nneh9P9pXh-e&dsoF zT2va(8J%Doa>$2=T?c>k_nZZN3<&1#0#8H$tK0rZR`BT(7 zjZg{qHB{$#*^%I0JlAZS#`p5Wr`Hpp_SU_>`ub0WZ;6d>K_2QYep3JqSg2`jXj?ad zxYYgj-{nOP9g=dtzCTI0w#1?{i@dX<(WifhPdAf6@VyK>*4MExh2(_&l5-q3RS(;G zY&zwrQGM@6Tvu4A%bAQmDp|_Gnp@Y3eAAeJ0CV_puL;{vIxt4wx!+)8_GV^HVhOTn z_O}4C&$(utbz5$e;Kfx+eqW(JpU)3vvH5+Nc1X#K627FLPJ{h}ERGRNY6IxUU@?hs zeaxy_(0Y-PuGG7w(tr5zM9IM9XtOi0Qx@Z^NDiXW!XgUv@X^l}mBepQUq;ky3-F@iDJp!YFgDl z`eE0r>aCT|cR=p9P_Ot!-!)?B`pum8u*LsARDjIO*$6T00mz}2mvO9S316CGM^wH@ z2QhwvDya;M^vst|nT%>xJe8%I`^|ym-VvORZD-90UrARn@2*<-*uMH=XR0Q}{*|)# zk@)ld;tu*Bl*6m_5VeX6mjyz$6t{0~^De%I5OrB8P|np^>Ee8i`v(SZjBNsr39=3d zZ*9#R7J(P47A)Q2@-2rBJ(vH7vbTV%s_V9g58VhNDJ4jWlz`GDtq4d-g8@iON_Qv- zNC-%W(k0Rz(%nc)cXxejAAItC@4erD{}chwIeYK5*P3h2F~=P9#2U;~{_Y57wLJ+k zUS3|9I|aYpQkFnySXgggGKFEI{|t}yLLjh|jm=XjY<=l@!ntfKwjf8Cf39>V$V}Mt z(TOa?O`svmufMn7|4)~v&64m|d2zkLSfH$o*u23_&~+iJ46Z*0P_+ z1z1p$vDnkd5MWKpoYTgAxEa7weY){CFDN^6xSPBC*`FzQeA5_am*QC>B=D%uAO0_2MQno8xT(cgR}85lRNs=Jnw>aw_X*~xfX^L9EpIa@ z!F^Y=7#j#@L%anuvz+R8O&{dC?fA|jDpoxW@NSiB86m=6-04ULysjt8{IK0$kNty; zdFU82DQKR4lc)vGQB9S>&6w%yoFO@DB6_ir%bkz+In@}h&MIW>*p0xG)>TXHF?!Vk zV}=^o5l`yG#6%bt(Or?(ubI~DoFds;SCmxd(?w7*F|ia&pLsuukoXBX1Dl@^J`Cde z8}wchA;N%LrV07sg!MoQmVB`VFVOF=nst5kdnh z&V`4uyu4h(fjRo%6Pxa2j))0x2Zah%&LdI+_`tw;G%nk$1aJ*yt0TdlRoLZJx4r01 zmPpSV4kDnksGqC?;x$Qn2Wu!G%_1+vG)TNpDjMZAXd&cTm{;k|l7@Kc;salXV!F>z zHK*Rr;;crM;;5`TYm8ylM?h_ls#hN@X~!a2g{`VNP!+5BN0oA40S=L5VHcH@)N zZ%Oc^CwL3f1wOS-o2pA$@T)O$$83jlsBrFjQ6AyaMCLvOw@tEFYkjhkA6`%nQ@Un8 zt8?{8^u6IQTKRdh#Q4#!#`sZxyT~4ii`fYNf`A|5NSVu(4UEEQ7ldeYjBiU`bPxG6 zIpEQ3ib*{rqC^r<;?B#P z)Dxva{_jZfBmuPX5dK(iSiuR?$*zPPE*Pn^R4FMt!KKG(+#y}c`aKQ8wTZka{w>dZ zMX@eODGY@hI)!sYn`f@ukWanyUw*XL@LQFU990vc8;iHxX^#$2LL!DDTDUPzGF@rW ziRPvjtf>JLrvHr%zqiwZNK`lmIzCDGF?MRotJ3YoqSE8ZU}}nUJg<8R2*?QajiY#> z-+JHJRJf9qKP>8Y!>!PDxZe46X~Ub2bTNgmmKU`URpzs2x2^;3laxzHx<~wmBWm>H zuT(2oXn=i=E{$-plS%yXz`vT2kwRr`PoiqE4Z~UEg6WA?ui74!C_4?elfchwYZW;_ zYeU>+wJoCdGOW9`6#=$3Qt(iB{$p%x;3uMW9$HE4=4ehsu2%r_S#)1r$7_0woE!VF z@rbmvY|%`<$Yz_1W}_3Ki;Ct*ZOMk!-s+S33MDS7&qc(Hb$S|M{T9zeCo*4J3HTa zf$B}b-y^Wb0sZ&*EYl@svgSqLE-|w7)52%T&yy}D2d8p?^2Eou%frcX zC$t6?buYHFK(yL1sn<>voFB_~5;$B#oV!<=$y36mx}7l!DLd8T{E8MN z%XvKcuH1G+!hUf-ge50XHo2`LTIabL5IF2nn$q2l$P*KUBR3w^P0X*dug*tufWIHL z!aP%^9MIQA&lSe}i#fPST%>h3rt+`3zEfwb35?zxfGxIjyy_(Da6EpM>e`cTQi#vt z^40=fjMg_EEjNhUq3w37e^cxYlF4J2NNZgRepDVe+=jF7SjIS#NUX!oMEM^qlaNmX z5*|9J(@h^=%x|ia#rctz5q+mP%Gikmml`A6L#8M2;iD3}sAJ{yl_h=NA^tNB(N^3!`Z{* zV`lxLg$5e*wqh96YDAt?U<{>Yp4r-3FnE2HYG(MLgk~x^ykcyA!D&Tx!SPZ*kpZ24 zE_Y2Jh;B;LptEGD0wJzTR6R0b8w~Inev>+$zQc{aG7V{#4TBUbmZyhpgMcVmuTK59~YM<$d+oW%7vDx=x`<3qR z6q4zIDy#7BPWfujiM;e6hBU_Dni@|*lLQfhr5#kz~l%PuI)^HQ6-b>Rv&2(&lcKo||D%Asa7V3SJSx7VzYNCC zVu0Z-i$*&q2)c%~8hb=vfP$kCMBj~8~d2qZXOp5|IY_5$NX+b zk4}gXVjD7CB5J+;I7F%PYv#l&78}&RYa_DXA?nqhl=nc63I?;+$i3`u2$`iavs?Rp zGHNk#Nzq$CCl_}C{r_0 zas3tOo*Myd?B1enn=9d6D+5z~{rGP8yeaM@QgE)8grIXx>hUli|Ggh1;f4>zo%zf! z_8FGaN8E$n3n|)*OUjEYu(! zhCe{?-pDBSDoX9{+1Oc6Dc2OoZ@ z#5OBv$8t@Rm6H{sAtzDV#wZ{5cw5k9@kb8?Az9X;bF{j+HPJYR=gL{EaOqB6KN!%T z$&{`9mbU5yRRW~*|DSI5DkWgC&SfjabfS(KI0$E5(1XV?Y0#j0_dwu)4a7q<*BF`Z zh$()gAY8di@}bLQiyL&#Ql#$t0%F}ulKMnxn>AOg`XzC3p>ITe^OC@1`8)3sqJO<% zvvxt@?JpYgL|LSKZdO7QN#ky^RNTYW4J1psDBtarv-9xpPFk7gG3vSjedOWnj@Y$8>voeCDE`m~R)wPT}V=58bEBfE2>!Z5rWXp1` zsdxKam`YEj>7Z;A%2E72EZVAQN}&yf{3u;y@aGy(0w>%_;RSvX?i$#Obw3d>xHh{z=gFZ9iYF zl$tEiUDSKYDhUG?n8AK}ax=Gvn~@7LIJQZ%mKf$6Q-~ScjOH6>Y|;;MANmt{EcJ$% zJA1^8xglf}pguUXfIK{xLl2Akhtj2QVRAeH#gB;m3EYbV4EJ*!B^{hA`?0>2%fv%k3kW(@?cSSLa>3Y!h>@m zu0dztkL<7ESJ7xQBIOqQ4C)z4P{n91)^^H)F zO?iAt7kews=7*I-zm+)c(R1STm1%bL$H!3Mm}+Uhi4(2D-@#hvGrI99 zGUp($uMcSFuwtLIwfj5I`H5uN=XF@#Mhlsn&ZHigJzJbOD^w~xG+u13M@gb&IBXRy z*e(pGCM@4bTX5wanqM=VkL1pAL40fYfq~g(N!PxXo&KiZaPE)zSo+5fX_C8Q%%VJj zz1%Mp4zmyDpViNNkj_=C;#!SRQxMcW_0rH~Yu+(3t)FPCWKekbv5oflVVspPFV7ka zmVwYE8NRJ6HfwN3U1^P@(&Gw^)1EfkQvP|2`SJ;JXbCx3w#+AKygl#t^O+pvg&Id(BGn2DagkL)1&F;NR^Ylf`=-j zM}Pd%x?UFD)O&#f#Dib!mZ)zgJ1?my4WJyM;1$3GJ-xk2Y`DBvX{(m4wU2FjAi=UP41!P+QydH6`~(Tad}u$xgo)sU z4xdee92&S30A&4+Hc^7>RCB6vud1FDk1*Sb|LVbszyIKmDp<&FI3oN}*9tk*RsZPu zr1QJ&C0P2vq_W}l_4m`c%*4_EJ^T6Tuk2@sL-Q1?xVV1v|63#v|8#s5I^fE~VK*1a z->{oZj~W6DUZOC>`B#SPhR8EXy5BxOs`j5*p7bg2`TK|x2)%X|nDe4w7F$PO6CT{@B734^=jN(&*ZuWSSchJbGQsjn7S0nyf@RT6`t&&N}+N z|0r95Ff_pz<%>B_JLhn}f2OeOBy-LQfSx#XEIqj{rr0t`EAw;-RVxOnILW^^JjcTM zZ%^pyvS&(p@7NFn@ttCGKc!IjOfsGUmrUbncXY3UEQh_b4wJ_|>Na}AcG_`y;8yXM z&yFHC^=BL2G%??79Api)fd z*EaTbGZ)U_OX#B=c#VUm-)cV$7KUTf_&(qM`;Pa!4#mpNsmPJLZvOg=44K@c?TvSt zmcNTn^pLNrQ*1@3mOnUC8iD*B#Nkrs3-!_ z-DmE7eNTbIFYS8BzwQz`*La}4GnoMu_b|CX%pkaX4610rAI26-{ow;i>8EtXBh2oB zi1KmVQ^_~?hmK>ULhmTfDijkhJ=c-3dhYZFLo1VGhsCoSy1T1mLdJVN>>v!J z!|j=S$jWTux=mHw=9iK|R>Fw-4PP8Uz_?9@U@*|tC@XL0*>@xSmDM899ycc6ep5$| z6#hYqJXq~|t2ZqwJ%F$Z8ljQTb)NNi7ucX|2jvmwuFV)ekHXXMC=sIBpv^qZ)pNLch$A8R-hBf}ZNY6ex56<#4}`fvG=U3E80)ls`mwpo`i6okX~r zdH=FEBGU5mk$XP&pIg4H?n#K26)dZ}fcNye&w_FqiT|yf=64@pOQKKFIr#YcWp|-7 z!w*b-ebR`#tgKC$Dp@2pz}{aS$*u%|Bym@_nj9dWwLph!`(!mQB_-wIlsGMvanwXS z`Ww?=?FSpL%yjT!)*xmm;ioiK#|dnIXP(KGE(->@nKF3H7U! z(gj9X^9_G7{*o~k)p8%{_+2N$QacIVs}krN-~NrD+Zw$p{rZZwK?M=`w=tdcXc{O0 z8i%+fbq0k=>BudyhRS^Yc-or!g=Ufw!PQ{6L8e=-`$W+D<19PlA&Op$rON~O{UwJG z{y!{fH|R>)f4IYQa`-r0x2}7vxrE*ZZB%fKjEqD;>0D@N=$;%GKrB~nj+i%BdYeW5 zSuKVx`vF)=D}$^~11~e{FS&+^(ACYf5?Ef1I2o+|{>UA4L{L5HTUyEkqU7Y_V$~_} zhnGjmPQt1#(dAt=^rc!f0<9UZnb=n~cz!3#*%3d;S=MF$6sxL=;+&ovkq0em`{x&h?q zZ{GUDHxsZOat<(8o^ttf-(ciI2e|Y(vCkUAe`KElj@>Kr>;IgHB_eJ?xaDq4<{PIL zA}g?RBS;|~0E@CN{(yaGiT|^U7y4kYZo=|9qnrf$w;6 zj=848M&(q@rDv2oNXSQj}UP@fyLg>0T9Zxt3ODmu1pnF5Iu#6%??whpIeaH2* z?B^T82KL7T#rC^nd03$X$bL>Zr+&BOicq0-lI#%#huM=|>3M@3J-=2At4(ih41td{ zW}8mFj!lS+w9!f7%c&`}{qnQ%j;GYMhWrIPv*^<=nyx1@PYI0Me{z_&n(`)QI`XO| zx=ti(Kxh!YBF|OU(L4YcGEcsilJw{|B!kWf#9DEjYCle^qQ83LeK=Z9>2<9ibg&qJ zohM?QZ7>P>2E_Y%oT98x_D*ucv2Y)RTY`cvwKX3T*R~&?(7i7&f6tsl3?k;Y)WJv$ zI<`XHh^8L?PGwX(_`1O|sg$yz`aa6+bLENg&o`mzL2|HVN_Ad2TaMw0aF|Q7p0O*a zyXb1XLo$i2e#mQsi3s0saTN3^OeL-%!Ha3@1)}x|VKCx5keS3iY6nvhnSF$82>BM- zwr-54{;9A>!_0X_fZmg)j^%Z18+iHs{_K3QG9!O%u2JhzM90V-^Pn-jCh zc;}AC!zrlSvk|qixgp#g_D_%8*HJDcCL|_)F_@`RMFuzK<^9r6nV(o>_Pi{ruOePO zmHT|P6_nflF5D@J={0Hu$_?mYGOlL|D>SRWmRmneUh~?h&(GeZJ?Y)|*Ezx(x1Acs zZ{JJL^{NInX%i^Zq) zo$ZL`{5=}UmPDZ$DS#dXVpKrEs)umlE=vlo`#7{U=S--iX^Hz27Bj!(pZA<>l(4rL z)wQ_s1d28>ov@Zj|BJ=uS-EHe+|gGzJ>e`h4&tFpInySCAYYo1&P+`cybIhSN z`t63nSM7M{FhUElE68cYkzgqZG!Ux|+6LIWu@#lY62L}N z@j0>W2MPc-0&v%U<}&R+%AaeWwR3zIDPX9tPpR+?B_cjh4@tb&hyHxaqf1G9@-?OU z&rkuqVOIJ4Ka>4SPl$Lt9d62mdgI)@pO}<{04RXcva)?3*3j6~Ew$4_%2hK%hGEC; zlY3YAzF5j$gu#Zh?*IDffdjpuJih87V8HpWT<2}*-}TJtjDWdATt9A=72gROIHo0g zkWNAPSvrm1X%JU!0n?(%L<6&fmDqW+W8qX_kPUq|`ipUt-{Ww-0AnU_!!zmg;wTUxbui#*E5gD@22JZ|vlkr!TN| zzhUT-yAXE@2mBzGn)p|p;hBH^4;rn{ z9jb@-5m8z!BlI3c;FmGyv=A`o4>l8_RCo6$TP%cSJ!fu<{keJDOa|fJv=bCIQ~`3w zz7slav%bOx7WP%&;$C+e07#$(J)ZJ-hkt(dx!SCkMqeI9tm{NZ$9#L+pj&g+hKdJ`_?D`-N}7B~^Sf6*^2+ zR-b6XCtdOw(``=8hk`wruWI@`i}$g=|E0Qumw8nqa`i%wt6r5?Q#JWF%-|C~P{FsQ zG|OFy??hWaZ;ou4qXD3wFGxvd>fk_q!xfF*K>)-I8I9x5(nC`e*sz?Cy4clK zn1!^yJV~nFvg0KC@D^ww>EDZnqB!ZN(}F)8zp21rXT?paY=|&)PyCG0*sTq{*T|+4Ju9c_1$7li|RS*HVcboQk{E{kNGMyEJIQX!^6s9s`N?sm z$*wkNmpZcvCAnw+wZ}w%a@3n0q+%F0y-)Y?eJ|Njq&Vh2!h(XN*vLTRfx|g z-?JV%Mw~{^C=|0X-a!Ct;3^y~!hArvFaq&6Zj@4=z~E~p10FjwKXS(d7jx*@=AJkr zS5NUEcgIq!@Iv1V4nN%AgxEyj_!e@e7I0ez>Gt%B*pH!gOWErnuCe142TEd+Na8#S zN^~WC11QhAM7;e2J;flHb|Ly!Iscb0wQI&t5i{Nc1f+v0AKl9Rfkd`Q*}b$WYos}m z?0bF?cHtxX?DyOOVIbjq{Kp~~rRM*nLCZ)3bBI03vS983_PtDEYqMPBarLZ?r5rJU z4(QyXv5v=Ya)`#G7_>YYu}a!4bI`p|QU2x5YfY(qTzGX0;OhX=t^Y=9zK#ePZT2r5 zga(SO24<$7SO%pDTf~pcTDY7zwa=fPye`HC0EF~*e@(%aFb696;7X;M@FLX9@9J=& zxvd*QhmMGeiJ7lghX?|sJgxc*_fv=J+QLZ_L6v-0>{q5(!5{+Y%!S9$obs|+mEBkTX)=t`>@vH_fiyZ?kC%Iaf= z1ILyA3}k*LaBoGAlHucf1O?%`ypb-O7)|+&JY!98^^s*V-0% zrG-P*B6e?t48PYYZQtg7p;A-U=~kLmAcr^NRmlBshz^;l|hyp zi1nIJFxOOrGLhCvxCIe<>ua%8F&AE@%9%F*FmQoOF89_Fh4yv;RE(B^0WC`{54X%c z3#h_aXaiUE?AlGG4cTWA-Bxj~rwF!jB?&d#e8aDsJzQhFoC7j*NqtxDL_DT2L7hKD) zawg5&!m*NBJBB;QhgIr%{~3OJ(YK7+3Qsxyly~OAczA6fS?83P5xSz}e7sP_$1Mt3qoB_Iw}YQ^>JV~F|M3F{N6R}AOo<^ za3HJWAks>t42dR*SIsqjHROL)cyb5pfhVte7$M&)RT~A{&oDz$(4^eLU1`E%A(RJu zcMp*ow?Sdwkg(=lYrXWnJ_)_?SjF)=u{($)1$lfMDl~sjbp2amFRurg3Tg25fKIIh9m$FVms>kS{9~m~+LIJN{b$xr zY0U>n`(df{1D}dsjE9a|iP%b9mqh99rV{m+JlpH7^}hY8l8J;EDX=XrXLJY-VHr_l zjY0_4vtm=yU%!3<1nd3JpBgSvH_KJ`CC+gd}k9dKAKfWIiNn!!4qg)?T(e(6`l3#eDbl9eMsTCcYEQy zdr8uzYY&R+;SH(=3HgTFbLWq#s`RJ z!<5dnvk|MFv8=?4npgR%m~=RzwmOd z9`?WeG=TL7iSoGUQhY9%${{%KJgpk87!IKD8~5slfbmD9^dhQ8#wN|(g!XErK%4b@ z=4acw0)95@-~RquRT#*CsMq+}oWM}$t81ZcK#`>XGGE2zH`}s21hW{mPqAqI69ndn zR@>59$$3_{<>{Rqnat)vrAp5Kc)1V;fExE&^MAs36ddXLkP2?6V$6pdLl3TeWwMZy z+jlgyv;tMKRQDN|GTpQkF3VDkZvu?krV4zVQDW(~pUP)JO^Y*q!s!=S2+)WCB<|~J zZx1!#>D~mqbWlNOTY{8ZwO^VDmZ)qNA+RZ`CPH^TR}@_v1mq{$w3IAe^u#x0nRi$w z?*YE|YMT~`O3qvkQg;4=W~Gno0u)KIoKGQ;IKu(xWRFy*k3H0*e-gB$5Y&p|k#$jk z!9+3OS(AXefI|*t*~4U-d-ptYBqSKWsliACKAK!FUqXU?7^!ZD`0Hu6S$<$Q=dK&= zg_CetNKh&~MIKv_{qmSw_Z>voV)cj6-itlZpcniLj*>^+DTxTup#!t-SwdbCm%NO? zt@MYe(ZEC0k0(twQn>T4%Df&GDhU-F@`W4Eka>AxXjBs`+ceE|v|xn|L7fqynPK)q z%7e8C_^7tnkiw}z`MIGGd~PbDW3VFrMEXzI-g%`8n+Qsx-Bp2-Xk7c(fzO#-e%lh% zUWhyR_=Aih$>J+98|8LUWtcm9?I5oRbQfeFbx-9xvA)sN93;4JY{E(|4q;c1>Vg3* zyR3e8rw{*z-&+Zy*6vy@mnUB852|R2g3P5pWg{j(*wxQJLG^u%cm-KdqJ$_>o?hz! z(p)R+evZ%TZ)v8|rfl~48`j6=r%l6$gDxQ7go*Mb?XX)=_kSaS!`O|s1C76sY?pZIf?$Bif z2nG`88g7fBB2k@mb(~lI3lsYwI0D{3>e0 z(O?b$zE3q+mLR(9t?gC83#o&jA5?xIgS3t1?t&aSpN+Jx95f%rkwg-H3u)H@H>=hg zgTQji*HK|?uqNhF*@;)cv7X|+!Cf0(ii7*ZJ`*X^^Wh9dDQ$(a(=;rSm8yoiw z4Si+18YhH1sh&9=Hp*sLqkp+ziFwc%?qn4e5k^Er@Hic0S6>Ozq9*>+3@MTTB%-!8 zjA47!Fk$9rkx9o@rjM-lpSEZ+ZE$!oDANq$tnWjgO*W#Tp^@))=?WjBtHc~qkPEFTE z9qs$+XHNJLsO`Bd)DKjG%AN5sWM{&|=#A#tV0rP~E?T3fMRFf1-4BrQ*U_9m%sQEu zogwzA3I(6$weG^)^;-S*v*-sl_}?*~NPx+>@4>8wc=;|YEDQ-YQt-mBx{dZ9(owv07XLYO^r9ZT{ zJw!OlOudk!u-A0Y=;32(4Fz2UNXdG3Gvd6g{Tq@Y@6;fIaE`62+Bt zH*_LYT#yr~>VC=yEc{ks!Z}nY^LF`5H>sZhMM9X>T#r3dI~vPffY zGE2JhD}PL2fSzHSvV7u{g3P{8wB=|(0mUxge!-mP$EQl(EGn<#?Or{}7@I}rV}P;G z=K?mx57oO(;Ooh~w68#qJ)Mm=&f{_%2p|5JTK>v7Xbty@>}IdCxb(W0be+h7f|{>-Ou@?Xte6jd=?YFU;!Z%e=S?Z@k{T;G zkRLJ=3Nb788LsF-mF9Ge(E@^4VQJkzKAuy}EM3H%tgy1^==i@OP}=+98po^Xm19A) z9NzS}43jPF=#WrbInX#5E2GQ2JW%a1zX|-OP1!Nku zYZ8G*;^HrF+g;i|D)G#<4<_?EzBHtJi~(wGYd5Qpf1PlzF`ZJ8-*J=IomY|{k`SL5 z1~>a)@+}hRAA`%+^WGd)p`!mj9;5>B9A&L-5|~PH`{ZiuV%OK(*6>6~vIq4@Vk%z? zCPtLaR3z6v3vt)JV^2|qsA`GjxZfwn8~ZZ(+%z!OxaW2w{icyRypf5 zhtbTV+K`zO2n!P*Xg^pV^CQ-ER@8kA{VcAH9^C=Cla^Pgg8z3Z>f4VSe&fS~&^sQw z#Er@#^#`z3x2(ZESima-@5u$G+Uv@xWS_pL1s0U^s_finWEVoP1}J1MkpnKK30UCg z;KG9sYqGrWAgUJ7Sx*PQ6|@H@j8D@Tud#EZOc&O>a?o@FbRT4(~lsuV;nL!5w=+ALJy5|Fe!CyI=(Iz{41#=Z+n);n3EwiPkbMUf< z&(v_#-HVjw9wuhhx=Tmaq6sC~F#0er-hJXbTWAGnmhGMRGn}nMVF$`Em$PGjJdFC6 zm0KI4Lt)bZZOBip#rCU0hky_| zkp+R2r_4081S1;C-ZV}qAq69aI3n`~G2_(`=uh*t~Hn%niiY=oC zXY2l^UYul&T@>I@b=D0Rj^{L(NvM@tDVONZQNb>Q9U3 zGilIctUg7g$MR&TP_9w&sPyr$8}sZktJ++==zwc~=UYns7YmB)+TDXmXvk6{cbpNdR*GlY zxOZH0^UP!Y*4v1X`iEdB-D%S;S;4IdX@c*j2IOi}!^tWQraWTNh#i{L_w;b>MsyqS zWuD5;<0?pY6FZ>DQC=9ZXGqxk ziSqHy9jH?Dt!@b6TOEmOAfZizDdka&)8mHQaq5}f6`jPNZ}7Ro{LWV)kdKVN+kcHp zz};Rq3R~t*-O1Erk-A+bX@_bULGk5}n8ETT(Yb**_f4vsPK!E)v}h>Zr;~S8qs|bE zb5VvK$9#P`u%fxgVxOo|^95cyiNBuYXuy0(>wh6bY`|fW@9oq))Rx?*65c2iWUTgX2Y}@w{S-sz?aqVRDT}>o_mv`n&VbCJCr3E0Tc63FMFdr1 zp0<+D#eSb1qzzp}QC+zo=TL(GET$02&Tajol(MF7>cy-F63*ysoVSzy=d)&K~ zEm36mdA0|O0yUxNz;BxgHV){D)0yG3V&l=qIwGzqSe(Ld*M|-aes3BYzatu?=JgRt zcQL9fFq~#Z=pba%yrwP7$1L$OvgnbPCudNRT0GK?8n*9fEauuFHcT}&CfDF=wCoi9wU5z^Q zOMgc1z1I7P7M0tmxRe6^y5}ouPzqJ;bZ$~oq{==kuY099>G9tr33O^2q3QLtrWk*k zG7)?WBBzZj=gJDIIpDY7Xk5*!p;WFN)P)tL)v1Dn-==-+o1g?Kr;ebUx@-|V!zpvI7sRMb7 z{U}ZVP5z>D$p@|;aiv>tHE(J%{WUb{!KFMonR9Uab5Da}jFRs;wSbc77^H^*u}guR zQ2<==2=QeX=bfVefL7LM;er8o(R5wDhn*VMs$7-C4e~lPKMVeKmC@sdXY@G!B7Jj( z>pFlf`Z0>N$USnlE0_!Vhu?X z-2>7@`DVET58SDv^g<316>KJ?h)nsX{v}oPyBk2V>()Wu)BwELdjIoPRPZm=d<@xO z&%7(bBdUm;H?IoQgRk{>`4p4}Rj3Hv)&Wr&UeS*WD*7|VBt^1*XYG6+%wCaEP9|d6 z{8jeNKKTD+4;P<+bYi=LG#GL$>WFRQZar{XzZ(z`Fjm(KYi{QS`Pa{ zBy!7n=3>@sKnLaE$A_EgnQx}|q5;Am+;7;GoY~~TWhamH0JdMl78V2Fx4)cUq;ahEPdN(d9>2$FxHR3@yar=; z_N8duZ}WTm%x==Jm*<+)kWhL9eSs8}Z`rZ{xq35xl^fBopUM%gV->6d6+S*=|z44_tosu_1yYTmxorw{(Q@+xZM{P8YJULX~EMq@rOE>Ay zY2G5W3*=a-wtp~q7+elpTr_)dx3`&GNGs}$SXs=i=D0do%7o0On&ErRrsLFDjVpn? zi%Hp6)2_&`DPVl(Qe}7?*Q~#5RVQcI-+XguDIWt^L_(7lx>MqG_+|2)qRE-5=8KZy zams|=nHZx-s;ZScNt9Go+Cj5zX}v)7{l#nAN;7%4K;6xBC866ihZ$U2KZ|irSsh~( zgvla;@`OU)e~irB-k`cR<5^uTzkSL;gXk_wAGYjwQm?sx?Q-kd(NapVC+>Gdk>4N* zn7H50GgJE;mCpI{JYx#|tCoOJ73G)BxJEM}LeN~LLA&hwk$iG&EIDXmLczbM zLfP8dYV^7{i1T@)B~W*7+U2FCMMArVwk_FGk<6YxN)d~YJ9SFEk;$^F8Jx~Xp0DNS zV2DbeAY1RfyIzV%;Dv8yX8FOw@3kB5-R3a%8RhGZ_hCj}CT9}kw)ZJ%tG94zBTtR< zIyg*(w~ia46lsU$N^LL}pFh{jRuW2hUuUawIr7MB(Cd^$7&Ve5A@L3$DnXYN(|(RW zA2(6MSvJ#_7EqaJJ{8 z^1JrPv!aMRhtAR@62Ve@wZZkX@n%}C#jlq^1BWJ4M=QSs&blk;PM&j>u};gHFo%ZG z&wzh&wQF)S)X+30>YllYs;gtuKOudmGGO)0s1uO2{W9=-~(1X0^p@ zb@3%7No$sbxbc)eGG8TQ&Fs)LG`BuhY*-Sq${%48$(IIt*+zzQ2mdJgsS#V1NfmW6 zkZ$8_E5iyjMz$hZs1oaY{q0<0gqk-K{Lx*CKGeP^WZqhcu|NggA(Sjg@s>zh06TCz z0*K8;&5V@Cu{A+~6sZkskEDRmN=jbh7Z;xKchP_;t(9l+1FSnMoaFscyApwJlBmNp zJ@1hb-re-bA+7^uOpWH@<6|^?-JC3bL@h5$;|Dw*yQrH*{Y&S^=2=5C=UOahI?b0V8>&OJ!yyEg$h_&Lg6=nmTShJfxnm>CJs1vJg4?b!&~E32m2B+NAeo8Di}=#pcYGKUW9( zzO7FYNk@yU#BSGzBikCo!t3}SbrN0{+dXK()J8R7m+FpvXnUMi!ke{^`NUZxXlKlo z5^OHt6xvM*t9yJ=_oH)89KTCUp9n_qFbDR((nf95TbFbgASI^~zAKmcD%ef zlX4MI(W9SU|K+9(-k5T9hU@U$!i(%D(K*C#hBHpt=^Y;gNmVo}?%y20xoRbh=t@ZZ zJUFE*j)P3a52?_uf#ZT_rHQI}{{W``RLq7)91u`8j=%d}MR!WV|YGMhF8>ZmH=rsfF*d24dsa?|NgCW{5|zr= z?PL|-_{;RwxT00@x*)Io^X(f`)hI^$2^fwhIL-AS_`lACPE}NI5bLkdKFf4Yuu{jOXK^GC z%d6Y6fa4UcDqaiDU^aJ)ZIK95_3(O z3YOjKg0gG$q=pPdU!ESl&g<%0CH5E^5KIZ~5U~-XBXbtyc57cH18*etm%t7^5YAp3 zcAyMewrVo%>hk+oD2$TRTH(^Y*|0<_TNB5L$4n{pFuaC0mZU=WwbPCCN2W+UzC-#A z9N9O6lcs(;PxJ8E>l^Tfy@n9YB=lmpAgdwuBm*NpmiJ}oFeU0l;c4okSswk;?%nvTRI)hJaYQ%@{|?x zP1>(Fc7YFK4&d*X4fo1)&6DR0k|4Dm9vGf1I)9D)Rbc0K_5MKEkt)&FM?(uGm{Hw~ z+0E_M5}**$f*(Tgkl^E~w7^QSStD?K{dG5y`_h`;R%m55Ram%T?=$MWi~0;}N$N3J zJ59M)Y#47vzG>_X6QO9EbiHPafwi5J7B9YmTxMevXq=!L7Z9njC!xJnbfEX4_6F8g zNy&p>!(*8q-yh4Xu5VMcl}}!f*kXX0v`qo7pbh`6sbaZ7%`})};wN7Y!yotPp&VN~^IbJw9#Vwo5I(iz_r8!@iA(t_JH zKei7d9q9&ZS=mz0lkFLnoUYF*s%3N;RPV2joUYQB?_MRXOC}=nMz}85s~H>Dtig)$rY#cd)*<62~VsY)iClR-Ql8lxAbpuQrMd4tN!yo0z8oiixcNOAA`X(VRB^hP zK>r_v-=%Eba`olt^&S)a?DaiJH_vTn$t28KXOdQ^F4VU@q*fh+^{%%aFB_GZ`PVP) z_Dq=6jW-LqPH~gsua45p2!QQ;k$CH*kviiEMs8-_ve`WDW7EdGk|OGJCR_Jr3ja8y zHDyHNl;?OU7(God=2|{l?PAP+9O+v-^piZC>p-}ZHT~r6E>q7DnXKh2P44I4=G<3( z7B*0ok+uu${7%=-_UBsJN=oH62@-TMk`&j zM|rWBXjO!$L%h$s+@xYtet^)dq!j0*CJ7$we!6vyo?MOHz-)+xONQfcL>Yh;BQtj-n>Ye|5HXeMj z!I0p|+by!Vc6JDHpetT7pT@GFaFEln0&9&CJ%70f`=!5R7u#N z>BFON^DJiF0{x?e9GLrzTk)h=tqShim)M}*myHwO?jto756@P1Q}?pGH?A+sy~pA7 zLQan0wo zd+;u!iPJSd+l;W37n0L`{`k^BfIZMXcsi|SHJOh=chu80uc~Hye9qnI`6qq_!pC~; z!2z8fUTYK8xh{=UMW5Lz->tZKa#t>1^e!KnzeLa4_`rHxN>x#sz_+^Lu+rUqc>b&F zUd|)u>$-7dDdP`lLxi|dQ_{ZPTCj;byez4DLt&vmQL;ZtgUNA=z;v(%`H>s8#?f{5 zm!;J=L0E;Ow<40I2}l#Ze1o)oW~J<3NojvNa>mIyq^c)G5Ucq4YGNw?e}#PoT$69V z_h{*oMp8mR8k9yQr9?owySo{nh%`f`TUxrLyG13W6-L)UdJIOLd-y-kdCq&@^S<|o z?K8&UzQ%p+x_Vu?ms%`oYehbEItJ=F3{;kB)6LMctL(Djw2~_d2*4oR9n>hd9=m z=NpW}9KYc{V;uqVr6TczW+6J|J*Ml2&_R#sJ={zNA^Irq=bbL5IeVz&q^}?F{)>ze zvFKZ9JlKD)8KnfwR~6|ns^=u97DDOE+$0|&`!IEEvIp*{evMXKFbDIG;&iT-sVeDW z$yo9Wm}Bx9w-i{d^jlVLxL;BOdL$%T2BmA|tqiycBHI&p?z3}kR$1vxXHB-xI%>0! z=~%{RBkwTK>4)E(TT;Nr-n3->KG-W14&qkCb;b5H4m$Gu6GlIJk=m3aTbV9c#G&P- zE&fvqA$Jd8m(|Ous?ojP*yv)`%RwJm?d=zzG(M`C#-&ts4|x=N<5+mfwERKbZq_n* zFV3YxxtS4TUPFrN>{8tLnGEmb6bA6ZsjGy1-Ac=x@{FyK2@bv?SQOA|K{Z{nOaRW^ z+fTl%7O>R>^?e){A6v@+AUwuf^XXvPsr)5qbRMmCjLriFy}Ef*uKvrVORS7uXBCp~ za{0i>F75T)pu*GO!x7xfXdM%>HGlIFss$cKg8I1rx5r`b!zVT{^geDLJ_oBFa%imll)NxFdK5X!h;=0tJCY8|Ld{?7EqY|h* z3DURJO8bIJ$^ibfx+8P+-s2PRxJhdyQZ^^QCAF-s+jPFKf0m9q(8ymPbIV{HV-FFnZt$MJP44d?rF zvh%rj@+(O<#Xqf|SkZd|Zn$qj$|(RO|!=kDdKK%L{y)8!$!Bqz?3jx+Fk#PrwI z^f{(FRm{McV*92XR}W=RuTpJ9bKN&ZcU`f^=HEQ|>X{%k@y33@(XLGtb4L9uU&b(v zKmC3(gM2G2ASk$&GKC`uE2d6y`DnR!cK^7AsS6(4E!R0C9l0|fb=~?iBzZ7X)YL!f zgZ~}+-_l*S!-eg7zBDz*o=N);(Vk8Po_WSyw6(NU!jA7qYHS|2MAs1^=1Zxp;&6xp zk>{XACP)@}DdEosJ!hH}2BroQn{Dku?vK3)dE zBJh4%QhSK3QtG=5>nija^sD}&{o8_~&~hzR{&yO(lv{M`|AzuOb9|1fKHpX>S2u{N zVHg!K@w{AMBkHnZvd*cM;abQO75-j=8UOvM(IVT&)3U~pEB0*Uw1?UpP)SqNiNpA+ z{L$@Xb~8AvWY27O+%kvtVSg+Hu{ZN*8zX86>>vpf<|{bV@yUn@QYL3)- zU9$HV+O)jzbID1e#^a0TEKi(#-_iZ-Opf<@jWx%~1af!DkXCd6dsmu<5}->kWl4uV zY394tiL?W0?a#q{*11K0#MHHX`2t#K{zdlQ0~#guF>Ha(i|H|OL@h@t;%s-Cfr9X7 z_}BHv(>@xrmcrm(W9_hyUVotxuRg-hfgC@u@BCY3@VtMRb~4-1|M zn2h4#Kd|Y$UOM{|upLjJRs*n>wgZ68M6-$J+Sai+jFY+-W_{ zj)LdDA&3MSQQYeI*HT#qTBcu~h1^!Op#WgQqZjY4RU`^;oONFt1pwN< z)#zA_sjR4;6V1o7e-gX=?B8@ipiAYDnhhGdTR(tAVOIpotCkw2JN@^7@kv460Qzn( zAsCfNXAGbZ2as00baIXSm)%!Sjos{Mn_krD;L5!Mu!B_eQ%7{7>!U0L3fAuu2@(Ud0l4r=iB%^xa<%Xptvl(Ut)sXP(g*3w}o;r zU(+2sVx|8DsiuXhRxG4cu^>L0s6ictn@b$E8fF3d;vfa9)t0zZwr|E+Sz~56UlMyrw4D6iFxw+g# zvOqWm0M8P^B6f|wa{aoKelHxZV8@Rgk$YxZA30W*fcBh4o=N{jY~-G>b7dWpMba@4 zf2VwLGEsgo78?|FVW{Ca99RmB9XP$P+lg-Vm!>8?twk;FSLM_P-P3=56T`~3hy-1s z+SrE5VNdvB#BHNMr(hz>Y^SjkEW8d@`J(=$E<`Q(HO0QH>q9q8sN3m@%RIdo zmBUA>Pu6RG;753@zE|6YF891_w<6n#P1hue?GO0nw3C^R!b0TNaBiX_hsl(}B9>z^ zH^)f>b8aJgcvsweg&+Z&pvHJQU%IEOfB9pM1>i)icfFWnrfdJDWBVRz0GTwtGVHZUI{#&A;5@obc$1HMB9NINZd|Sze-P=YRyM=Ka$ufQgXD z98AfcIUoP&50%vVrmB|P$XZ-7k#lDxE=OZNbMULshgiHz`QBA4>nZD&6XxKnisu7A zbvvSP;*cIvaR0W5qGpZdq{6RA1@Z29HDk|}g%sVDuhvJ0b$GyQEkLC*O3(7#dylBG zLy(kjRn#@k)jWA!(mkbe!d27>u1_A$S4&cwsi4874jqLhk6u!BD`8$qrQH0K*efpe zzdpEOe9(_=EQ5rEL1!=E@K=4)OfJ59~|+5HOKzn zDAv5!r7d1mWZ3~|pZ%y@_lEm2P*b!shva8k#rS*EB|375`OZA?!OT435V+NN@8O&c z^jRW{7Cg*V1ufDw9MCHOx4h2C)Qyio-dNUU%_$bGwsX34xfbYdNal>gc?B&;hV_^# zt~kjF(@$d>T#@pMk&e4j-;1h)>qzeojG6>9+7_!RHgq^JmCBSEe&hL`>2oJA;3|Ru zSQ)Op|0f))U1O($1c1)kql8&3tX(QM4}+iZGy4`Ax!hW|FrGKA1%4|(r__+}l>(u> zYIHYx?%zp2te6hcdplx?VCo2d(y4w{Tp=Oa+@1pfF@r6F-P@gNL$C=D;F6= z_A==>wO0GfkFK9qH4~bh8M{So|={mwM%zG@W%86MdYVp&Xr#4GQOSMCiL#`G! zgG*W2yhm zYLuSw@9POu1h5}^pH{?TcH)4P_*AFpx5~`Q7F-kojd;LhKH#pK&W`c{N>3d{(*=Ies}Gssw+zq14|tG!E6X8-!PI`vZ$){M~A>6b?md>hYJ`&hpptw zk0&K*BhnRDeK|fH08g3I|AMX(%Tqm@;sW;Np?Ju6q!kZX6nAQG5a5h>NCuY04;VeGco|G!xiK@X9h!m*iThoZ$oO=ZH6|f$;Vcd5 zerSpvplt|d*jqJhTGW!kUj(mzv-5kFcCn5iMX1g|D!!>kN*uFi8=Z1%yr}3TD7_*f z9pM5CfS7vp!=HR%gvA8PMKcgCABlkl3c7nwwZ$17=h5VK$PT&X;k3>4I0pbFg_GnV!zQ#hkczHzx67 zp4X)NFo}7az1Zp16veGFx67kD8t)uk?eDqBd489Z`;s-I>;0r%7nb8j4I-LZiQFW; zwkn`KHM=keDFAF4x6`Qmu>z4$_Xh6n$=)xI-;DFmADNU=jZKzZdPGY&`Y>N^EMrM_ z2H#hXlxU^uHC*7}ql5m6Y^n=ai&(G#f>W=#Hl2kd__geec4iQ zWY0CTa^z(>CTZoUNI!5#dakdW10}z=g6Y*)$eP#uNR-+;uN#ajG*9y#X4a(M709Ni z-gZ$|Q4)5M{Spj;1(s)cPW=(P^Sy~NDpJv?+`;&chqDWAO{6DR=OfT$`*AiR_>XJj zA?j-F;s0;cAZ2z(UjWJSH#V30eFx~v|C@TtsW`Eg$E6EN(ezOK!y+dJV+Z;$6W>)bdY$DT>908xR6+1aa=ol5wdZlBEyR%;G zrss|ut2&2`Wzd2mHPl04f)Z3o7}IS$!@CoM@i_VqW1PZBn59{e8zsRMkzen-!GriC z!HN{qjxSDAp|Lgv@tSWc2E_dKa5;}V;vnb)A1}5qTbPvYQ7;|{yfaQhOx^Q=vkW{6 zB6tEDdqim7T4S9-3Xvg&^l?zKxGWZXbm4>C?(9sWjfc*aVuH4sqMk&EKC=_U2ayrB{>DIVz$e=hSib2Q@fht<5uf~8$Ktccx@GqGpq~qt%=IQ?R2Ru^GB)Y7 z<8B82PS-S?h%U&XOV>k-i(`}R0i$A>eg;)}g@LQosIU^Z!MxTl4J4DqsFn2de2-5K znDYNLAp3pJht|ENdGMtMmlqJ^9iBh}q<^TBPI#S@)Gh^YBsQxV$-i7bO68*d&2cO# zBwkpw8_Tn}0z(+R{!k3K7NiS@3iXruVm2(fc=ha)Nvz1|{Z2mNLDjy<YTJ|dJ zt=Y_m50Zyg)pUStJzF)%V%fQKABnu3`4^XcxR<{>uLy1qb{&8R*K}jL|I;?@Wx`y> z-?SM8UwsKEENBG34H2NvcERBr?5L?0pJw^p$AkUni?d4nv`6be1-|=fFHwEz3 zc1-%&5q%Ld-HNGEwx<4QRhK#Ac1KnXu))2r=kSUlx*7iE6UE3jcQw-~#}mGupN!q( zdr2_=?Xhi*8l3H>n{veZlf6e1tM5}<{Gt+mx$KIK(eVv^*o+TUNJAujo;|J&Bz|R` zqwl+L)dYrk;xHMx%CBAD;4BA}b-Ai;0^L}jRPW~JpEU`{Vpwd}|+MUAZ(5pj$C-na)4)}x^uQg?^W4%!#! z6{hnyYI3h!pY_d+o=kZ~;BNqP9goAA*MEoNi>LXpVP3-jbQU0cBAo2mtC+{x)*pLXOe}WbWV0uJGJABdCA( zW-&|Y>FSjE*<8I8Ds51LoZtLzy~*X=mmpr+$B7cnRvu+-Qt=fiTK)7aS1)NbLPl^U ze7Ho3&t>4U$&aJnG3{}#uQL1CxCMTDfiGz~!SGwS!f1iIsQUZt{7>YWZ-*dx*m#BS z<}+XE>DOl%(SAssKA2}5-K!l<+0^$jr=s-hw8?fy9A8N<+A?nV)B9g6>>rc9yhgHK zu43GT-JG4e^7~!5{Kyq~fe7}vSJXlIc=eSOMn6J6ti1As_HJF;ea0T}0 zM!M(CwDs(AnmcTvp^33izD|+$x?kvcto5qviitP9q~!G?GqSO>FKa!+ZL|9!wFxz` zSOCM?mOt;bBk8K+^TrPOUB|;>)oUll; zZ@aohkk3Sh#lHmsT|d>?=Rz}j=G;G|3A*hB55!sX=GZgMcar}=@^>ugDyedMR)!VZ z;5+@rJ$13DvZ!Wm0GCEC1<1fOmGax)63+N{_JwPs^Sat+o;xkG*r3wfspD*O6k|iJ zW@0uaE$X{3!&A??d;L)sx8_Qu<7;Wh{T%#^=Nzd{i!<{bEsFZXiuk>#@>?`PF@jm> z81!N~b|a-B>YrNKM|Rk0aq97B726A?-8~8cbH|f-htA)bnT+Vii4o6$Lelv6_j*o> zo}P7qW&Qbp8~SMX$O9DT6sS@CkW-z-1No{`!dyHSFH%41d`E$^?cQyFt}mH(SWo|Z z4q;j{>P1s?CrgFa*9-4DA;V|o>V|5(A&0a~Nj=Sra`2oRT^{mq?d5sbyw$KW zi?m3)0pz?0Q}PSFVEU;-jn59_o}KUD8d8wL?Fs1K707y%88h z#!|QcURSl9cGpGOGkm$Lf4zIVmQ+}^NX=~gFGV#An)pX}!YO3b+)h8ff4{3j%JJ}_ z8qYY-#Pl>f;LX_+56plc?62Qd=wn$A4ME@aBS7QKdKgSR=8iy#x3;eC5E{6@oTO`l z%jq_S|6-850r@U>6X#>%47^=w=!Yx;NH>O1kv1#8=ckp*0}t}~u#@Thd8o)w+sq4q zDj?sYbjJ|C(x7_3em2j!yxO}zn$Y5b#rK>WHX=r8o@D!E{Wd=VN}hvG9?BoQ&z?PN zW9Qs`_wHS_+w#*IRXO1@yYPy|D(7CViM9mHiaWZqT*_oe$H!rKMuT`Sz;RQ)UbE>j zn7a5*BAWtsvmnP{^Z;;}p1F+!Ct@=eAP7Wzy(ei1ux${B%Dyfn%ipYvPsKHNR9BA& zu1Mcpoh?nnPfh|udqI9DHkO}6hWHR)v!o|F=?Ns(4Gy(Dy@0qcpc)9E%laoYWa3In zx`-&+^MAG4w=*(Q8Nfz*AAC#5ifbC93rp3jA!cGTL@9-Q_+aG6Uc$xRA_IK1wt?x( zBqXFYM+CC|@x#ugA^)-F?yYs5+}$~J71_Zj$=38zfD}^%2I?$73sw4g)AurYPF$9m zlok30B6Va1ZMxI(Cv~-R^LpMdw7ajQ?al^|;TjKOE0X4#lN;hI_|By439J1NOMRpqPn!Z)_CBw6)XPHu#_ zuF4@efSOHiCban6jVE1fTE;PAq0&i5gXhqBtlSY{`i7%a0XABR@R=zRI#v2zN9`Dy z5G#-@%w1YmaR81rNdH1RH8t$RG`c(SRM^|A>YH$xjd5!yjX#b8Y`P|!u>|<73?y`1 zcw9gjX_u41C$qV|4+x9;VQ)dAto4Ci-d*ALQ(rgrrc%fjmu5yZ#Xr4E zNtsuDK%F^vPR$Bo#*>Jk9{#Nyl6o_hiE7_kypSntFwcNQel*#+OJGcI@@ z7y4!gjmf|tr@e6zP){ec5$G6)g z7&A_N?&6n=%$uVlkHnOeUT9$ugSQL^Erj#Wy5ep%BkqrDU?D9q|E*FTNNK%rO6D+Q zB>UQSVfs6|QHWsT>mBfHQ!%x5RM&n#dphlmNw4F60MsaA_1(of(yO4M@u__PmFpy0 zNTW?ua7bH>uN2%7?B+LYa569;()P;g^?Ls+cgXltfp?}?CEVO{=4ufyDxYONdg5;8 z_F_R*nC+zUTRnx+_O4q*u=C>yP(iuq4nmRcmn8fe?F?*{51kD_#3$p%eVR~2%m-~} z7VmA+{K#y?wX+KiID0~Xy!r-6$2{#9^3>7Lvu!9UER5r}n<9%oKoKZdzHj@EHL}x1 zfyfvm6?dYZ$MVpQg$sK7LbPjwn*(*mR%GvQ*Oh3L_gF1 za0W?#_RhYhw9z$$LWe}$z|8W3Dq4Vj1T(BV>UD69x^R+0rHW@JX_)l3=}jm(c9`;% zAwv8W79<}_v?1gZb+1g0r%GLE$I;yBHeMd5ytZtwK9dTT)T$gkSN#W+DYgUhxs;LBhW9wA@{p zwD^uPqdIRY2jX z#n!#8XrjB*nBvc^$VPw6oQ+Pzwq4%!$|gm)kJb~~;i3Z@7mqovVMIhk|IgGQ+iL7u zU@aOy@d+?xC(0%G@ne)(>Pjp}#L%(kOpg6DixQEWCa=GFLOLkK8K9O~R4U(k^JOMF zQN+-2!n{$}f5xxEL#EGRp12&ZpPIR_oTAyj8r|A^#Y;BtGuf{9=Y`JBN>y9}iC4KT z$WY(784Pmpffnb$oz#KmFH^bIiQ8cl>@mclcfatdzpBq-x$w-b@+rN`I`29`?DBo zUsKEO^uGUCwu0)ga7)6{}@X;!LOOZvoDwLtG+rSbnVN!Yt%6a z*sbqP);@)Y<(v#olST`mlXW$pABm0D$Uu%>@I3R0BBM>Q>NOiuh?+ja1ZCz=+W;5! zu(l%@R|Hap4w{tg;93F*S+^utwMsaIWz-!n-(zBjXkJOpca+5#qIev-Xw+1+7;+Vm zLsPu-K05%TWv&=H+kK~>di8w+&D@Bm<#z|xbgO`wLQ9gc2i)^@N)y#$bX#q+Rf{qY zf7lM#)4nP=^I!V-_jg!;l|tWFXI~O74e?zRo%F+4eR}tmu$fym8illw4VpFOK6{9a z1kkXIb{&I}+AR(L4IF1h+t!SqnpxFRMZnPX@7gE#WrR*j?Nx1Y8%~j{B+eD^VFd2_ z%>D@sO^G>3zv$Lazp5HsC3ST!=w#2T2_uUZ80eY zX9}r*qf-HT6_fbk1KGS*d5={&j_KE&`7YhKq^^`_7AQucTIj^~T@|hi#6Av)UefP{ z)6uUMZ*Jtp)N1Mvh5E)u3=qH~ib+qW)oE3TPf7X$aLG3J`xFBbjSHERt762sS&QaIOiofH}DUoX#1R}PkY0sB4D47+4Nw1kI} z&m7q5T0mtU-!W*M#_!5shwv${q(A@FO!F}wO6stdL+(M_XpbST8cCct@^kVhN=*P-sD*Oo- zDRFjDIQBej8p{=^_)90V!<&-qaG2cS2EsILZM}CoIF-ReBMS5nWZozgmj|c;`v7T4 zF&U)_TL9=p+aMtgi0)NmHUQbl+vAhh=BVk)NVVR*&g$|xAgZj&%g@J%AZ8pma5Kvh z4Nw#TLJ;kWg;F@Qkq>os=C#Y`(t*gmTL=F%>vWD;cGa}b8|FXlR5%ys*zh6JvEirH z5-LRh<=9|Dk;u#%NJqJdAs1nGZKu~W4Jd3_+1jqQBcQ$9Rc&N1mP)B|<2js?3ap&? z^f6K@uz`4TzG^45EvV0^B(z;c%=*FHn-3zqvkoJyK7qJEP>Jz3s1#I>!Ka~lo?q7g zjx}zW@8bsn{OL=AK0n{Gu8ak2r)n7E;DdUru;NGIQYfu9X+(tsv4w2M1{y>#@2gm->P!w zp;#cLhD3|=r1vkh0~d|%`}NFN;Xn6yjf{RYPFP3?AHIHmkRA#JK>+sU-3K-Xv*I%B z>OAtX6yF$Rfow;wNPlA$A~StCDD%Uljr}%*Lxr2q9%6p9RQza71JrDR1Mt&*m>rDV z4xMq2gKGX+sE2AOAt+ARc@%5!Kl$*XMzRP?ZQ=RHM5iY}kLUSwkL9$bQnye26Q3{e z0!YL3FhI|EEXHEE_t@v=BJtY=BBS6T^g#UcvOs1gcEjfChe;;q9xzdXnUi|Fq?)lwmtcH-}2cZ|$zopUq5Qu`qC}=RfdQ}I zdh4Yu^@JaXJr@wg7T~3FK?`Lj#m$!2yP|2sq9Uu7RQBhlsjFr;w<;>zK%MCC!D$h+ zAGnCWEjnl?e61uoBzImp_iJnn1Xy$U$EIazDrX4HgR#dYN=cLI^%3o^rcxiQWLH}H z&sMHfnoj3f_IJvjg`Uh&HTlAO^_E*gAB7aZ&HY&cA!!$bkdFOpdsVgE=ew6E0q7`iw;lV zg2)X+&0T?5#6vk#(;U6*q?h=m2lFHJYiny}>+>$c-~$d&Xre)A>84M7sUtk)zL1AX zaBRRSAkJL7bg1V)Yw3)m#82aat z6W^Ki^f9j*94RXJDFu|+xF0Br2A2kpi4g(SiM6!oYWS<2vp26|g`A8VH}9CtwqyNn zbnZ^yB5H#NUYRQNMwypA72LF#vXxOx`ojYa_!e#*egpDE1a4gkQ=E^|9`3BVSQ^aU+WX^BJff*!^aNU+M`Fkf(=pgbU9=sp$%sTEcrQ$cy_Dp|Cbyk0~XG)ml z-d4-Bzh$}!P_X$_MAZ-w?1~#+&BL0IoJ^@b2Gb}>AqCXP^7PrIiHl-d4`(YE{G4V& zdTN?M5-a`c!f9*Q0h5h^*KvXrxJzqQ*6^C+~fxREkt@y8o_I`FL`b-%i z|1N{t4OG-5Pko|HPml4)oP-=d=bB6UQy37f|Dl|vCSPibb-8a|sGRmS`NMqpNQ?zX zo|3S{p5+4Ad(Zg67myBHGr!6Q2YS;FRtobh7^2czQKh9^iEHUeEu$U(45p9G@VTZz zsZ(oREVL!jX}tX66bO^WB_(;12i7FQL=tYt=Et5I8|HS9aY<_Fef?4If`$^WL^x9@u5N;-R} zeJAbEKwJCm$_jZ?^WlTFba<~m5Glz3RijyM3Qj&gMR|ECBO3o9!RHCUPBe-Iql4@5 zgY3R1@AJ~q7dkrOrKRWv$TS^nAdI@ldKY*;I|T2siBW7`9*b9zb{><+` zV>@b?)2+Virv`U*Ci7*MmUQ&rFxeMA*aBQ{IK8ZFS!r7(LvEmNzO4tR)zjm)>yEK~ zOIYU>{sO{{dZ&3sb1N&yV>S>U&3d*Mmt(g0xdsCbk55_9vh0Iu2|CpwcXf8v5DboB zYn)km8<-{6+{r*8Kdf4lmuFD_&11|GM@XS0^%XnXLQ4DcaQ_JJ{o-=UR#JJ)_CUpb z>G7R??w|XX?citNedyh3*)fSqlPq8heLyK7z&lTiNl+u;*6iYMi0#@;LQY-=BkU6d zYA7suU*VhcA&fJk!8W@koFJlon=#r4uUvZuGCCE&o&1)LOYGPmwGz0L6AHAQe%j)3@ZYaEsoZZ8XG`nGmFN9CsBM{wJ!qj!9;$8O9b{lD|Mp}qEGWR7miRspaFBHQl`v>Z z4>w5cz9=de!hD={okRTv(3b;s0dhe7>{S(pjd`7>Qt@+6a)GV2r%=GlUQL?-Rk`P}A~`*g+E)t(oGkXlvr!=4O4KQSps= zGReB}+)~1hiXgb|^M|tQAHRY^E6MvyoKw6nZcdJ#OWu4}@H3FSf@2CbK)*{=2(&rB zdTvOvy@!tIwdRDhBF0c&ewhuV)Rg>ciLBvmk^JYR?76t<@92Qz% zI-qeec0}b|o#;aKt5(j2FE~EMJ{Bx$s)D-1VFpF3-U@Pe9m3ZKHI0#prOD~(u&eg| zXCGo`&3-68tpW;nNsFGb`mOIH#P&kxW^)J-&baL$m zQv}vdmnl(-C%3s4sTzjzPQr3aE}j7zsL{xc4G4$|*5Y;qL!sH-npZcBG?=rV5@cGh QLBOFbuP#^l)a=cF08!H*7XSbN literal 0 HcmV?d00001 diff --git a/dsolovianov/clickhouse/Homework/image.png b/dsolovianov/clickhouse/Homework/Типы таблиц - Homework.png similarity index 100% rename from dsolovianov/clickhouse/Homework/image.png rename to dsolovianov/clickhouse/Homework/Типы таблиц - Homework.png From 860d31c75c469e5ee453102823c94ff69609df6a Mon Sep 17 00:00:00 2001 From: dmitry solovianov Date: Fri, 27 Feb 2026 22:23:37 +0400 Subject: [PATCH 11/48] revert f7b9920af2f7251ac0340841cbcbe149cb7eedcb --- .../Homework/Типы таблиц - Homework.sql | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 dsolovianov/clickhouse/Homework/Типы таблиц - Homework.sql diff --git a/dsolovianov/clickhouse/Homework/Типы таблиц - Homework.sql b/dsolovianov/clickhouse/Homework/Типы таблиц - Homework.sql new file mode 100644 index 0000000..af9dcc3 --- /dev/null +++ b/dsolovianov/clickhouse/Homework/Типы таблиц - Homework.sql @@ -0,0 +1,81 @@ +--Задача 1: Создай таблицу page_views +DROP TABLE page_views; + +CREATE TABLE page_views +ON CLUSTER clickhouse_cluster +( + user_id UInt64, + url String, + view_time DateTime + ) +ENGINE = MergeTree() +PARTITION BY toYYYYMM(view_time) +ORDER BY (user_id, view_time); + +--Задача 2: Создай таблицу users + +CREATE TABLE users +ON CLUSTER clickhouse_cluster +( +id UInt64, +name String, +updated_at DateTime + ) +ENGINE = ReplacingMergeTree(updated_at) +ORDER BY id; + +-- Задача 3: Создай таблицу region_sales + +CREATE TABLE region_sales +ON CLUSTER clickhouse_cluster +( +region String, +date Date, +sales UInt64 + ) +ENGINE = SummingMergeTree() +PARTITION BY toYYYYMM(date) +ORDER BY (region, date); + +--Задача 4: Создай таблицу user_metrics + +CREATE TABLE user_metrics +ON CLUSTER clickhouse_cluster +( +region String, +avg_age_state AggregateFunction(avg, UInt8), +active_users_state AggregateFunction(uniq, UInt64) + ) +ENGINE = AggregatingMergeTree() --Подзадача 4.2 +ORDER BY region; --Подзадача 4.3 + +--Подзадача 4.4: - Вставь данные и Читай их через `avgMerge()` и `uniqMerge()` + +INSERT INTO user_metrics +SELECT + region, + avgState(age) AS avg_age_state, + uniqState(toUInt64(user_id)) AS active_users_state +FROM +( + SELECT 'Samara' AS region, 25 AS age, 1 AS user_id + UNION ALL + SELECT 'Moscow', 30, 2 + UNION ALL + SELECT 'Moscow', 22, 3 + UNION ALL + SELECT 'Samara', 22, 4 + UNION ALL + SELECT 'Sochi', 34, 5 +) +GROUP BY region; + +--Подзадача 4.5: - Читай их через `avgMerge()` и `uniqMerge()` + +SELECT + region, + avgMerge(avg_age_state), + uniqMerge(active_users_state) +FROM user_metrics +GROUP BY region; + From dfc094300c266acbc4b3ebe150aa5c25a64e9fa7 Mon Sep 17 00:00:00 2001 From: dmitry solovianov Date: Fri, 27 Feb 2026 22:23:59 +0400 Subject: [PATCH 12/48] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20dsolovianov/clickhouse/Homework/=D0=A2=D0=B8=D0=BF?= =?UTF-8?q?=D1=8B=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20-=20=D0=97?= =?UTF-8?q?=D0=B0=D0=B4=D0=B0=D1=87=D0=B0=202.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Homework/Типы данных - Задача 2.png | Bin 112412 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 dsolovianov/clickhouse/Homework/Типы данных - Задача 2.png diff --git a/dsolovianov/clickhouse/Homework/Типы данных - Задача 2.png b/dsolovianov/clickhouse/Homework/Типы данных - Задача 2.png deleted file mode 100644 index 3e8757a70e49bd7cec059bddf534fb262cd007c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 112412 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

1Bor0tk7k1}a_EU$IX8@lzF#ed0{Q|>sP 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

S6sXME1(=eOFFI)}P3ea&K?6G^nTa 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 QLBOFbuP#^l)a=cF08!H*7XSbN From 27f21ebd444e7a3de4b8dd1e46489f9fe93d6884 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Fri, 27 Feb 2026 22:25:27 +0400 Subject: [PATCH 13/48] =?UTF-8?q?=D0=9D=D0=B5=D1=82=20=D0=B8=D0=B7=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../clickhouse/Homework/Типы таблиц.sql | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 dsolovianov/clickhouse/Homework/Типы таблиц.sql diff --git a/dsolovianov/clickhouse/Homework/Типы таблиц.sql b/dsolovianov/clickhouse/Homework/Типы таблиц.sql new file mode 100644 index 0000000..af9dcc3 --- /dev/null +++ b/dsolovianov/clickhouse/Homework/Типы таблиц.sql @@ -0,0 +1,81 @@ +--Задача 1: Создай таблицу page_views +DROP TABLE page_views; + +CREATE TABLE page_views +ON CLUSTER clickhouse_cluster +( + user_id UInt64, + url String, + view_time DateTime + ) +ENGINE = MergeTree() +PARTITION BY toYYYYMM(view_time) +ORDER BY (user_id, view_time); + +--Задача 2: Создай таблицу users + +CREATE TABLE users +ON CLUSTER clickhouse_cluster +( +id UInt64, +name String, +updated_at DateTime + ) +ENGINE = ReplacingMergeTree(updated_at) +ORDER BY id; + +-- Задача 3: Создай таблицу region_sales + +CREATE TABLE region_sales +ON CLUSTER clickhouse_cluster +( +region String, +date Date, +sales UInt64 + ) +ENGINE = SummingMergeTree() +PARTITION BY toYYYYMM(date) +ORDER BY (region, date); + +--Задача 4: Создай таблицу user_metrics + +CREATE TABLE user_metrics +ON CLUSTER clickhouse_cluster +( +region String, +avg_age_state AggregateFunction(avg, UInt8), +active_users_state AggregateFunction(uniq, UInt64) + ) +ENGINE = AggregatingMergeTree() --Подзадача 4.2 +ORDER BY region; --Подзадача 4.3 + +--Подзадача 4.4: - Вставь данные и Читай их через `avgMerge()` и `uniqMerge()` + +INSERT INTO user_metrics +SELECT + region, + avgState(age) AS avg_age_state, + uniqState(toUInt64(user_id)) AS active_users_state +FROM +( + SELECT 'Samara' AS region, 25 AS age, 1 AS user_id + UNION ALL + SELECT 'Moscow', 30, 2 + UNION ALL + SELECT 'Moscow', 22, 3 + UNION ALL + SELECT 'Samara', 22, 4 + UNION ALL + SELECT 'Sochi', 34, 5 +) +GROUP BY region; + +--Подзадача 4.5: - Читай их через `avgMerge()` и `uniqMerge()` + +SELECT + region, + avgMerge(avg_age_state), + uniqMerge(active_users_state) +FROM user_metrics +GROUP BY region; + From e943afb57d0b3865fead1e00f64ee1506cf8e3b4 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Fri, 27 Feb 2026 22:30:04 +0400 Subject: [PATCH 14/48] - --- .../clickhouse/Homework/Типы таблиц.sql | 81 ------------------- 1 file changed, 81 deletions(-) delete mode 100644 dsolovianov/clickhouse/Homework/Типы таблиц.sql diff --git a/dsolovianov/clickhouse/Homework/Типы таблиц.sql b/dsolovianov/clickhouse/Homework/Типы таблиц.sql deleted file mode 100644 index af9dcc3..0000000 --- a/dsolovianov/clickhouse/Homework/Типы таблиц.sql +++ /dev/null @@ -1,81 +0,0 @@ ---Задача 1: Создай таблицу page_views -DROP TABLE page_views; - -CREATE TABLE page_views -ON CLUSTER clickhouse_cluster -( - user_id UInt64, - url String, - view_time DateTime - ) -ENGINE = MergeTree() -PARTITION BY toYYYYMM(view_time) -ORDER BY (user_id, view_time); - ---Задача 2: Создай таблицу users - -CREATE TABLE users -ON CLUSTER clickhouse_cluster -( -id UInt64, -name String, -updated_at DateTime - ) -ENGINE = ReplacingMergeTree(updated_at) -ORDER BY id; - --- Задача 3: Создай таблицу region_sales - -CREATE TABLE region_sales -ON CLUSTER clickhouse_cluster -( -region String, -date Date, -sales UInt64 - ) -ENGINE = SummingMergeTree() -PARTITION BY toYYYYMM(date) -ORDER BY (region, date); - ---Задача 4: Создай таблицу user_metrics - -CREATE TABLE user_metrics -ON CLUSTER clickhouse_cluster -( -region String, -avg_age_state AggregateFunction(avg, UInt8), -active_users_state AggregateFunction(uniq, UInt64) - ) -ENGINE = AggregatingMergeTree() --Подзадача 4.2 -ORDER BY region; --Подзадача 4.3 - ---Подзадача 4.4: - Вставь данные и Читай их через `avgMerge()` и `uniqMerge()` - -INSERT INTO user_metrics -SELECT - region, - avgState(age) AS avg_age_state, - uniqState(toUInt64(user_id)) AS active_users_state -FROM -( - SELECT 'Samara' AS region, 25 AS age, 1 AS user_id - UNION ALL - SELECT 'Moscow', 30, 2 - UNION ALL - SELECT 'Moscow', 22, 3 - UNION ALL - SELECT 'Samara', 22, 4 - UNION ALL - SELECT 'Sochi', 34, 5 -) -GROUP BY region; - ---Подзадача 4.5: - Читай их через `avgMerge()` и `uniqMerge()` - -SELECT - region, - avgMerge(avg_age_state), - uniqMerge(active_users_state) -FROM user_metrics -GROUP BY region; - From 980aaf9638d814ce56c6f5b9c2f5d0d36bedd40e Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Sat, 28 Feb 2026 00:02:04 +0400 Subject: [PATCH 15/48] =?UTF-8?q?=D0=97=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Homework/Homework - Типы данных.sql | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/dsolovianov/clickhouse/Homework/Homework - Типы данных.sql b/dsolovianov/clickhouse/Homework/Homework - Типы данных.sql index f15301b..68c8236 100644 --- a/dsolovianov/clickhouse/Homework/Homework - Типы данных.sql +++ b/dsolovianov/clickhouse/Homework/Homework - Типы данных.sql @@ -57,3 +57,35 @@ FROM ( ) WHERE DateTime_Valid IS NOT NULL; +--Задача 3 +DROP TABLE IF EXISTS user_activity ON CLUSTER clickhouse_cluster; + +CREATE TABLE user_activity +ON CLUSTER clickhouse_cluster +( + user_id UInt32, + actions String -- JSON: ["login", "purchase", "logout"] +) ENGINE = MergeTree ORDER BY tuple(); + +--Тест данные +INSERT INTO user_activity (user_id, actions) VALUES +(1, '["login", "purchase", "logout"]'), +(2, '["login", "logout"]'), +(3, '["login"]'), +(4, '["login","purchase"]'); + +SELECT + user_id, + -- Сначала реобразовал записи из набора "каких-то" букв (String) в массив строк Array(String). Потом считваем длину массива и дальше суммируем длину всех массивов действий для каждого пользователя + sum(length(JSONExtract(actions, 'Array(String)'))) AS count_actions +FROM user_activity +WHERE + -- Проверяем наличие 'purchase' в массиве + has(JSONExtract(actions, 'Array(String)'), 'purchase') +GROUP BY + user_id; +/* +Преобразовал записи из набора "каких-то" букв (String) в массив строк Array(String). Нашел пользователей в новом массиве Array(String), совершивших действие "purchase". +Просто написать actions = 'purchase' не получится, так как изначально actions просто (String) и соответсвенно "["login", "purchase", "logout"]" нельзя сравнить с "purchase". Поэтому сначала преобразовываем в массив, а потом с функцией has(array, elem) ищем то, что нужно. +То есть менять бы не пришлось, если бы в actions было изначально разные значения в каждой строке ("login", "purchase" или "logout") +*/ \ No newline at end of file From 8c2a5fcfc8d015a6b269665b8a7fb40285c6fd02 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Sat, 28 Feb 2026 00:46:40 +0400 Subject: [PATCH 16/48] =?UTF-8?q?=D0=97=D0=B0=D0=B4=D0=B0=D1=87=D0=B0=204?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Homework/Homework - Типы данных.sql | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/dsolovianov/clickhouse/Homework/Homework - Типы данных.sql b/dsolovianov/clickhouse/Homework/Homework - Типы данных.sql index 68c8236..05b588e 100644 --- a/dsolovianov/clickhouse/Homework/Homework - Типы данных.sql +++ b/dsolovianov/clickhouse/Homework/Homework - Типы данных.sql @@ -88,4 +88,30 @@ GROUP BY Преобразовал записи из набора "каких-то" букв (String) в массив строк Array(String). Нашел пользователей в новом массиве Array(String), совершивших действие "purchase". Просто написать actions = 'purchase' не получится, так как изначально actions просто (String) и соответсвенно "["login", "purchase", "logout"]" нельзя сравнить с "purchase". Поэтому сначала преобразовываем в массив, а потом с функцией has(array, elem) ищем то, что нужно. То есть менять бы не пришлось, если бы в actions было изначально разные значения в каждой строке ("login", "purchase" или "logout") -*/ \ No newline at end of file +*/ + +--Задача 4 +DROP TABLE IF EXISTS sensor_data ON CLUSTER clickhouse_cluster; + +CREATE TABLE sensor_data +ON CLUSTER clickhouse_cluster +( + sensor_id UInt32, + value Float64, + status Enum('ok' = 1, 'error' = 2) +) ORDER BY sensor_id; + +--Тест данные +INSERT INTO sensor_data (sensor_id, value, status) VALUES +(1, 25.5, 'ok'), +(2, 120.75, 'error'), +(3, 15.0, 1), +(4, 9999999.99, 'ok'), +(5, 0.001, 'ok'); + +SELECT + toString(status) AS status_string, + avg(value) AS avg_value --Среднее значение value для каждого status +FROM sensor_data +WHERE accurateCastOrNull(value, 'Decimal(10,2)') IS NOT NULL --Фильтруем строки, где value нельзя преобразовать в Decimal(10,2) +GROUP BY status_string; \ No newline at end of file From 7dcea750a3aae04ed7a687db9a7a13aa87149931 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 20 Apr 2026 00:14:25 +0400 Subject: [PATCH 17/48] =?UTF-8?q?=D0=97=D0=B0=D0=BF=D1=80=D0=BE=D1=81?= =?UTF-8?q?=D1=8B=20-=20=D0=A1=D0=B8=D0=BD=D1=82=D0=B0=D0=BA=D1=81=D0=B8?= =?UTF-8?q?=D1=81=20(Task=201=20and=202)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Homework/Запросы - Синтаксис.sql | 224 ++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 dsolovianov/clickhouse/Homework/Запросы - Синтаксис.sql diff --git a/dsolovianov/clickhouse/Homework/Запросы - Синтаксис.sql b/dsolovianov/clickhouse/Homework/Запросы - Синтаксис.sql new file mode 100644 index 0000000..47d7629 --- /dev/null +++ b/dsolovianov/clickhouse/Homework/Запросы - Синтаксис.sql @@ -0,0 +1,224 @@ +/* Запросы - Синтаксис*/ + +--! Задача 1 !-- + +DROP TABLE IF EXISTS users ON CLUSTER clickhouse_cluster; + +CREATE TABLE users +ON CLUSTER clickhouse_cluster +( + user_id UInt32, + name String, + age UInt8, + country String, + is_active UInt8 +) ENGINE = MergeTree() +ORDER BY user_id; + +INSERT INTO users VALUES +(1, 'Ivan', 30, 'RU', 1), +(2, 'Anna', 25, 'RU', 1), +(3, 'Petr', 45, 'RU', 0), +(4, 'Olga', 35, 'RU', 1), +(5, 'John', 55, 'US', 1), +(6, 'Alice', 42, 'US', 0), +(7, 'Tom', 38, 'US', 1), +(8, 'Lucas', 28, 'BR', 1), +(9, 'Maria', 60, 'BR', 1), +(10, 'João', 27, 'BR', 0), +(11, 'Kenji', 33, 'JP', 1), +(12, 'Yuki', 29, 'JP', 0), +(13, 'Chen', 40, 'CN', 1), +(14, 'Li', 48, 'CN', 1), +(15, 'Fatima', 31, 'AE', 1), +(16, 'Ahmed', 36, 'AE', 1), +(17, 'George', 24, 'US', 1), +(18, 'Nina', 34, 'RU', 1), +(19, 'Max', 50, 'DE', 1), +(20, 'Sophie', 22, 'DE', 0); + +--Получи 10 самых старших активных пользователей. +SELECT + user_id, + name, + age, + is_active +FROM users +WHERE is_active = true +ORDER BY age DESC +LIMIT 10; + +--Выведи пользователей из country = 'RU', отсортированных по имени. +SELECT + user_id, + name, + country +FROM users +WHERE country = 'RU' +ORDER BY name; + +--Что произойдёт, если написать LIMIT 10 без ORDER BY? Просто выведет 10 случайных активных прользователей без какой либо сортировки. +SELECT + user_id, + name, + age +FROM users +WHERE is_active = true +LIMIT 10; + +--Посчитай количество пользователей по странам. +SELECT + country, + COUNT(*) as user_country +FROM users +GROUP BY country; + +--Для каждой страны выведи минимальный и максимальный возраст. +SELECT + country, + MIN(age) as min_age, + MAX(age) as max_age +FROM users +GROUP BY country +ORDER BY country; + +--Отсортируй страны по убыванию количества пользователей. +SELECT + country, + COUNT(*) as user_country +FROM users +GROUP BY country +ORDER BY user_country DESC; + +--! Задача 2 !-- + +DROP TABLE IF EXISTS dsolovianov.events ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.events ON CLUSTER clickhouse_cluster +( + user_id UInt32, + event_time DateTime, + event_type String +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/events_v2', + '{replica}' +) +ORDER BY user_id; + +INSERT INTO dsolovianov.events (user_id, event_time, event_type) VALUES +(1, '2025-07-17 09:00:00', 'click'), +(1, '2025-07-17 09:05:00', 'view'), +(1, '2025-07-17 09:10:00', 'purchase'), +(2, '2025-07-17 10:00:00', 'click'), +(2, '2025-07-17 10:05:00', 'click'), +(2, '2025-07-17 11:00:00', 'view'), +(3, '2025-07-16 12:00:00', 'view'), +(3, '2025-07-16 12:30:00', 'click'), +(3, '2025-07-17 08:00:00', 'purchase'), +(4, '2025-07-17 13:00:00', 'click'), +(4, '2025-07-17 14:00:00', 'view'), +(4, '2025-07-17 15:00:00', 'view'), +(5, '2025-07-16 20:00:00', 'view'), +(5, '2025-07-17 01:00:00', 'click'), +(5, '2025-07-17 06:00:00', 'purchase'), +(6, '2025-07-17 07:30:00', 'view'), +(6, '2025-07-17 08:45:00', 'click'), +(7, '2025-07-16 23:59:59', 'click'), +(7, '2025-07-17 00:01:00', 'purchase'), +(7, '2025-07-17 10:10:00', 'view'); + +--1. Добавь колонку с кумулятивным количеством событий по `user_id` (используй `count() OVER ...`). +SELECT + user_id, + event_time, + event_type, + COUNT(*) OVER (PARTITION BY user_id ORDER BY event_time) AS cumulative_events +FROM dsolovianov.events +ORDER BY user_id, event_time; + +--2. Сделай аналог ранжирования событий внутри пользователя: `row_number() OVER (PARTITION BY user_id ORDER BY event_time)` +SELECT + user_id, + event_time, + event_type, + ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY event_time) AS event_rank +FROM dsolovianov.events +ORDER BY user_id, event_rank; + +--3. Что будет, если ты явно задашь `ROWS BETWEEN`? Поддерживается ли? +--Да, `ROWS BETWEEN` поддерживается: +SELECT + user_id, + event_time, + event_type, + -- кумулятивное окно (все предыдущие строки) + COUNT(*) OVER (PARTITION BY user_id ORDER BY event_time + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cumulative_events, + -- скользящее окно: текущая + 2 предыдущих события + COUNT(*) OVER (PARTITION BY user_id ORDER BY event_time + ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS last_3_events, + -- окно: предыдущая + текущая + следующая + COUNT(*) OVER (PARTITION BY user_id ORDER BY event_time + ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS prev_curr_next +FROM dsolovianov.events +ORDER BY user_id, event_time; + +--4. Сделай `WITH recent_events AS (...)` — все события за последние 24 часа. +WITH recent_events AS ( + SELECT * + FROM dsolovianov.events + WHERE event_time >= '2025-07-16 15:00:00' +) +SELECT * FROM recent_events +ORDER BY event_time DESC; + +--5. Используй CTE, чтобы посчитать топ-5 пользователей по числу этих событий. +WITH recent_events AS ( + SELECT * + FROM dsolovianov.events + WHERE event_time >= '2025-07-16 15:00:00' +) +SELECT + user_id, + COUNT(*) AS event_count +FROM recent_events +GROUP BY user_id +ORDER BY event_count DESC +LIMIT 5; + +--6. Добавь второй `WITH` — для маппинга `event_type → category` и используй его в основном запросе. +WITH +event_categories AS ( + SELECT + event_type, + CASE + WHEN event_type = 'click' THEN 'engagement' + WHEN event_type = 'view' THEN 'engagement' + WHEN event_type = 'purchase' THEN 'conversion' + ELSE 'other' + END AS category + FROM (SELECT DISTINCT event_type FROM dsolovianov.events) +), +recent_events AS ( + SELECT * + FROM dsolovianov.events + WHERE event_time >= '2025-07-16 15:00:00' +) +SELECT + re.user_id, + re.event_time, + re.event_type, + ec.category, + ROW_NUMBER() OVER (PARTITION BY re.user_id ORDER BY re.event_time) AS event_rank, + COUNT(*) OVER (PARTITION BY re.user_id ORDER BY re.event_time) AS cumulative_events +FROM recent_events re +LEFT JOIN event_categories ec ON re.event_type = ec.event_type +ORDER BY re.user_id, re.event_time; + +/* +Вопрос: поддерживает ли ClickHouse многоуровневые или рекурсивные CTE? +многоуровневые CTE - да +рекурсивные CTE - нет в классическом понимании, а скорее в итеративном смысле. +*/ + From 8c6daac203ecdde1ad934919d6a763f36e85e6a9 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 20 Apr 2026 03:32:36 +0400 Subject: [PATCH 18/48] =?UTF-8?q?=D0=97=D0=B0=D0=BF=D1=80=D0=BE=D1=81?= =?UTF-8?q?=D1=8B=20-=20=D0=A1=D0=B8=D0=BD=D1=82=D0=B0=D0=BA=D1=81=D0=B8?= =?UTF-8?q?=D1=81=20(Task=201=20and=202)=20v2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Homework/Запросы - Синтаксис.sql | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/dsolovianov/clickhouse/Homework/Запросы - Синтаксис.sql b/dsolovianov/clickhouse/Homework/Запросы - Синтаксис.sql index 47d7629..abd02d7 100644 --- a/dsolovianov/clickhouse/Homework/Запросы - Синтаксис.sql +++ b/dsolovianov/clickhouse/Homework/Запросы - Синтаксис.sql @@ -2,7 +2,7 @@ --! Задача 1 !-- -DROP TABLE IF EXISTS users ON CLUSTER clickhouse_cluster; +DROP TABLE IF EXISTS dsolovianov.users ON CLUSTER clickhouse_cluster SYNC; CREATE TABLE users ON CLUSTER clickhouse_cluster @@ -11,8 +11,11 @@ ON CLUSTER clickhouse_cluster name String, age UInt8, country String, - is_active UInt8 -) ENGINE = MergeTree() + is_active Boolean +) ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/users_v2', + '{replica}' +) ORDER BY user_id; INSERT INTO users VALUES @@ -73,6 +76,12 @@ SELECT FROM users GROUP BY country; +SELECT + country, + uniqExact(country) as unique_countries --возвращает точное количество уникальных значений в столбце country +FROM users +GROUP BY country; + --Для каждой страны выведи минимальный и максимальный возраст. SELECT country, @@ -90,6 +99,18 @@ FROM users GROUP BY country ORDER BY user_country DESC; +--Всё вместе +SELECT + country, + COUNT(*) as user_country, + SUM(is_active) as active_users, + MIN(age) as min_age, + MAX(age) as max_age, + uniqExact(country) as unique_countries +FROM users +GROUP BY country +ORDER BY country; + --! Задача 2 !-- DROP TABLE IF EXISTS dsolovianov.events ON CLUSTER clickhouse_cluster SYNC; @@ -104,7 +125,7 @@ ENGINE = ReplicatedMergeTree( '/clickhouse/tables/{shard}/dsolovianov/events_v2', '{replica}' ) -ORDER BY user_id; +ORDER BY (user_id, event_time); INSERT INTO dsolovianov.events (user_id, event_time, event_type) VALUES (1, '2025-07-17 09:00:00', 'click'), @@ -220,5 +241,4 @@ ORDER BY re.user_id, re.event_time; Вопрос: поддерживает ли ClickHouse многоуровневые или рекурсивные CTE? многоуровневые CTE - да рекурсивные CTE - нет в классическом понимании, а скорее в итеративном смысле. -*/ - +*/ \ No newline at end of file From a997d586da7ffc4ebe563b31c0737545bfa29484 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 20 Apr 2026 03:36:52 +0400 Subject: [PATCH 19/48] =?UTF-8?q?=D0=97=D0=B0=D0=BF=D1=80=D0=BE=D1=81?= =?UTF-8?q?=D1=8B=20-=20=D0=A1=D0=B8=D0=BD=D1=82=D0=B0=D0=BA=D1=81=D0=B8?= =?UTF-8?q?=D1=81=20(Task=201=20and=202)=20v3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dsolovianov/clickhouse/Homework/Запросы - Синтаксис.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsolovianov/clickhouse/Homework/Запросы - Синтаксис.sql b/dsolovianov/clickhouse/Homework/Запросы - Синтаксис.sql index abd02d7..120b341 100644 --- a/dsolovianov/clickhouse/Homework/Запросы - Синтаксис.sql +++ b/dsolovianov/clickhouse/Homework/Запросы - Синтаксис.sql @@ -11,7 +11,7 @@ ON CLUSTER clickhouse_cluster name String, age UInt8, country String, - is_active Boolean + is_active Bool ) ENGINE = ReplicatedMergeTree( '/clickhouse/tables/{shard}/dsolovianov/users_v2', '{replica}' From 2ced7cf273b03896b1e2c1d2a3c63024b83dafe2 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Thu, 30 Apr 2026 22:58:25 +0400 Subject: [PATCH 20/48] =?UTF-8?q?=D0=97=D0=B0=D0=B4=D0=B0=D1=87=D0=B8=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BE=D1=82=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA?= =?UTF-8?q?=D1=83=20=D0=97=D0=B0=D0=BF=D1=80=D0=BE=D1=81=D1=8B=20-=20JOIN?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../clickhouse/Homework/Запросы - JOIN.sql | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 dsolovianov/clickhouse/Homework/Запросы - JOIN.sql diff --git a/dsolovianov/clickhouse/Homework/Запросы - JOIN.sql b/dsolovianov/clickhouse/Homework/Запросы - JOIN.sql new file mode 100644 index 0000000..29496d9 --- /dev/null +++ b/dsolovianov/clickhouse/Homework/Запросы - JOIN.sql @@ -0,0 +1,70 @@ + +-- Задачи на отработку Запросы - JOIN -- + +DROP TABLE IF EXISTS dsolovianov.products ON CLUSTER clickhouse_cluster SYNC; +DROP TABLE IF EXISTS dsolovianov.prices ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE products +ON CLUSTER clickhouse_cluster +( + product_id UInt32, + name String +) ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/products', + '{replica}' +) +ORDER BY product_id; + + +INSERT INTO products VALUES +(101, 'iPhone 14'), +(102, 'Galaxy S22'), +(103, 'Pixel 7'); + +CREATE TABLE prices +ON CLUSTER clickhouse_cluster +( + product_id UInt32, + price UInt32, + region String +) ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/prices', + '{replica}' +) +ORDER BY product_id; + +INSERT INTO prices VALUES +(101, 999, 'US'), +(101, 1049, 'EU'), +(102, 850, 'US'), +(102, 899, 'CA'), +(103, 799, 'JP'); + + +--№1 Сделай ANY LEFT JOIN, чтобы получить цену любой из регионов. + +SELECT + p.product_id, + p.name, + pr.price, + pr.region +FROM products AS p +ANY LEFT JOIN prices AS pr ON p.product_id = pr.product_id; + +--№2 Что будет, если в таблице `prices` несколько цен на один `product_id`? + +/* Для одного product_id будет выбрана только первая ЛЮБАЯ (ANY) подходящая в поиске.*/ + +--№3 Как повлияет `ALL LEFT JOIN`? Почему в ClickHouse его избегают? + +SELECT + p.product_id, + p.name, + pr.price, + pr.region +FROM products AS p +ALL LEFT JOIN prices AS pr ON p.product_id = pr.product_id; + +/* `ALL LEFT JOIN` в Clickhouse ведет себя также, как LEFT JOIN в SQL, то есть собирает все совпадения. + Начинается перегон данных между таблицами. Из-за этого растет нагрузка на ОЗУ и CPU. + короче, по сути ALL LEFT JOIN создает декартово произведение*/ From 46a366c07a5fe579ae23b9cfac39c32ec69280ee Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Thu, 30 Apr 2026 23:59:43 +0400 Subject: [PATCH 21/48] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BD=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D1=81=D1=85=D0=B5=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../clickhouse/Homework/Запросы - JOIN.sql | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dsolovianov/clickhouse/Homework/Запросы - JOIN.sql b/dsolovianov/clickhouse/Homework/Запросы - JOIN.sql index 29496d9..6d6edfa 100644 --- a/dsolovianov/clickhouse/Homework/Запросы - JOIN.sql +++ b/dsolovianov/clickhouse/Homework/Запросы - JOIN.sql @@ -4,7 +4,7 @@ DROP TABLE IF EXISTS dsolovianov.products ON CLUSTER clickhouse_cluster SYNC; DROP TABLE IF EXISTS dsolovianov.prices ON CLUSTER clickhouse_cluster SYNC; -CREATE TABLE products +CREATE TABLE dsolovianov.products ON CLUSTER clickhouse_cluster ( product_id UInt32, @@ -16,12 +16,12 @@ ON CLUSTER clickhouse_cluster ORDER BY product_id; -INSERT INTO products VALUES +INSERT INTO dsolovianov.products VALUES (101, 'iPhone 14'), (102, 'Galaxy S22'), (103, 'Pixel 7'); -CREATE TABLE prices +CREATE TABLE dsolovianov.prices ON CLUSTER clickhouse_cluster ( product_id UInt32, @@ -33,7 +33,7 @@ ON CLUSTER clickhouse_cluster ) ORDER BY product_id; -INSERT INTO prices VALUES +INSERT INTO dsolovianov.prices VALUES (101, 999, 'US'), (101, 1049, 'EU'), (102, 850, 'US'), @@ -48,8 +48,8 @@ SELECT p.name, pr.price, pr.region -FROM products AS p -ANY LEFT JOIN prices AS pr ON p.product_id = pr.product_id; +FROM dsolovianov.products AS p +ANY LEFT JOIN dsolovianov.prices AS pr ON p.product_id = pr.product_id; --№2 Что будет, если в таблице `prices` несколько цен на один `product_id`? @@ -62,8 +62,8 @@ SELECT p.name, pr.price, pr.region -FROM products AS p -ALL LEFT JOIN prices AS pr ON p.product_id = pr.product_id; +FROM dsolovianov.products AS p +ALL LEFT JOIN dsolovianov.prices AS pr ON p.product_id = pr.product_id; /* `ALL LEFT JOIN` в Clickhouse ведет себя также, как LEFT JOIN в SQL, то есть собирает все совпадения. Начинается перегон данных между таблицами. Из-за этого растет нагрузка на ОЗУ и CPU. From 4a602481a386862925262b5674acafa30d5e837f Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Fri, 1 May 2026 00:02:20 +0400 Subject: [PATCH 22/48] ORDER BY product_id, region IN TABLE dsolovianov.prices --- dsolovianov/clickhouse/Homework/Запросы - JOIN.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsolovianov/clickhouse/Homework/Запросы - JOIN.sql b/dsolovianov/clickhouse/Homework/Запросы - JOIN.sql index 6d6edfa..21108c6 100644 --- a/dsolovianov/clickhouse/Homework/Запросы - JOIN.sql +++ b/dsolovianov/clickhouse/Homework/Запросы - JOIN.sql @@ -31,7 +31,7 @@ ON CLUSTER clickhouse_cluster '/clickhouse/tables/{shard}/dsolovianov/prices', '{replica}' ) -ORDER BY product_id; +ORDER BY product_id, region; INSERT INTO dsolovianov.prices VALUES (101, 999, 'US'), From d1acaf78a69955c61bbd38dd5a6e5a799a2006fb Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Fri, 1 May 2026 00:06:47 +0400 Subject: [PATCH 23/48] =?UTF-8?q?=D0=BE=D1=82=D0=BA=D0=B0=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dsolovianov/clickhouse/Homework/Запросы - JOIN.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsolovianov/clickhouse/Homework/Запросы - JOIN.sql b/dsolovianov/clickhouse/Homework/Запросы - JOIN.sql index 21108c6..6d6edfa 100644 --- a/dsolovianov/clickhouse/Homework/Запросы - JOIN.sql +++ b/dsolovianov/clickhouse/Homework/Запросы - JOIN.sql @@ -31,7 +31,7 @@ ON CLUSTER clickhouse_cluster '/clickhouse/tables/{shard}/dsolovianov/prices', '{replica}' ) -ORDER BY product_id, region; +ORDER BY product_id; INSERT INTO dsolovianov.prices VALUES (101, 999, 'US'), From 209cce48b2d60233217735a5c452395f0429e247 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 4 May 2026 07:16:07 +0400 Subject: [PATCH 24/48] =?UTF-8?q?=D0=98=D0=BD=D0=B4=D0=B5=D0=BA=D1=81?= =?UTF-8?q?=D1=8B=20=D0=B8=20=D1=81=D0=B6=D0=B0=D1=82=D0=B8=D0=B5=20-=20?= =?UTF-8?q?=D0=9F=D0=B0=D1=80=D1=82=D0=B8=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Homework/Индексы и сжатие - Партиции.sql | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 dsolovianov/clickhouse/Homework/Индексы и сжатие - Партиции.sql diff --git a/dsolovianov/clickhouse/Homework/Индексы и сжатие - Партиции.sql b/dsolovianov/clickhouse/Homework/Индексы и сжатие - Партиции.sql new file mode 100644 index 0000000..4e9ebb8 --- /dev/null +++ b/dsolovianov/clickhouse/Homework/Индексы и сжатие - Партиции.sql @@ -0,0 +1,146 @@ +-- Индексы и сжатие - Партиции -- + +-- #1 +/* +1. Создай таблицу sales с `PARTITION BY toYYYYMM(sale_date)`. +2. Выполни `ALTER TABLE ... DROP PARTITION '202405'`. +3. Что произойдет, если не указывать `PARTITION BY`? <- удалит все данные из таблицы. партиция то одна :) + +*/ + +DROP TABLE IF EXISTS dsolovianov.sales ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.sales +ON CLUSTER clickhouse_cluster +( + id UInt64, + region String, + sale_date Date, + amount Float64 +) ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/sales', + '{replica}' +) +PARTITION BY toYYYYMM(sale_date) +ORDER BY (region, sale_date); + +INSERT INTO dsolovianov.sales (id, region, sale_date, amount) VALUES +(1, 'RU', '2024-05-01', '100.0'), +(2, 'RU', '2024-05-15', '120.0'), +(3, 'US', '2024-06-01', '90.0'), +(4, 'US', '2024-07-03', '150.0'), +(5, 'DE', '2024-07-04', '160.0'); + +ALTER TABLE dsolovianov.sales DROP PARTITION '202405'; + +SELECT * +FROM dsolovianov.sales; + +-- #2 +/* +1. Создай таблицу с `PARTITION BY event_type`. +2. Удали все события `click` (подсказка: это `ALTER TABLE DROP PARTITION 'click'`). +3. Чем такой подход может быть опасен (подумай про кардинальность значений)? +При большом количестве уникальных event_type создастся много мелких партиций. +*/ +DROP TABLE IF EXISTS dsolovianov.events ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.events +ON CLUSTER clickhouse_cluster +( + id UInt64, + event_type String, + event_date Date +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/events', + '{replica}' +) +PARTITION BY event_type +ORDER BY (event_date, id); + +INSERT INTO dsolovianov.events (id, event_type, event_date) VALUES +(1, 'login', '2024-06-01'), +(2, 'click', '2024-06-01'), +(3, 'click', '2024-06-02'), +(4, 'purchase', '2024-06-03'), +(5, 'login', '2024-06-04'); + +ALTER TABLE dsolovianov.events DROP PARTITION 'click'; + +-- #3 +/* +1. Создай таблицу с `PARTITION BY cityHash64(user_id) % 100`. +2. Что ты выиграешь с точки зрения баланса? +Данные распределятся примерно поровну между 100 партициями. Упрощается управление удалением старых данных (можно дропать целые партиции) +3. Почему такой тип `PARTITION` не ускорит `SELECT * WHERE user_id = 456`? +Потому что партиции определяются хэшем, а не прямым значением user_id и к тому же сортировка в партициях по log_time, а не user_id. + +*/ + +DROP TABLE IF EXISTS dsolovianov.logs ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.logs +ON CLUSTER clickhouse_cluster +( + id UInt64, + user_id UInt64, + log_time DateTime +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/logs', + '{replica}' +) +PARTITION BY cityHash64(user_id) % 100 -- 100 партиций по хэшу user_id +ORDER BY (log_time, id); + +INSERT INTO dsolovianov.logs (id, user_id, log_time) VALUES +(1, 123, '2024-07-17 10:00:00'), +(2, 456, '2024-07-17 10:01:00'), +(3, 789, '2024-07-17 10:02:00'); + +SELECT + id, + user_id, + cityHash64(user_id) % 100 AS partition_number +FROM dsolovianov.logs +ORDER BY id; + +SELECT * FROM logs WHERE user_id = 456; + + +-- #4 +/* +1. Создай таблицу с `PARTITION BY (region, toYYYYMM(visit_date))`. +2. Как будет выглядеть имя партиции? +Имена партиций будут в формате: ('значение_region', 'YYYYMM'). Пример: ('RU', '202406') +3. Сможешь ли ты эффективно удалить **все июльские данные по `RU`**? Да. Удаляется целая партиция без сканирования и нагрузки на систему. +*/ + +DROP TABLE IF EXISTS dsolovianov.visits ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.visits +ON CLUSTER clickhouse_cluster +( + id UInt64, + region String, + visit_date Date +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/visits', + '{replica}' +) +PARTITION BY (region, toYYYYMM(visit_date)) +ORDER BY (region, visit_date, id); + +INSERT INTO dsolovianov.visits (id, region, visit_date) VALUES +(1, 'RU', '2024-06-01'), +(2, 'RU', '2024-06-15'), +(3, 'US', '2024-06-03'), +(4, 'US', '2024-07-01'), +(5, 'RU', '2024-07-05'); + +ALTER TABLE dsolovianov.visits ON CLUSTER clickhouse_cluster +DROP PARTITION ('RU', '202407'); + +SELECT * FROM dsolovianov.visits; \ No newline at end of file From 1de11c1d5e7a45835fa6c8ae39f36c1f734a2dd1 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 4 May 2026 08:09:54 +0400 Subject: [PATCH 25/48] =?UTF-8?q?=D0=98=D0=BD=D0=B4=D0=B5=D0=BA=D1=81?= =?UTF-8?q?=D1=8B=20=D0=B8=20=D1=81=D0=B6=D0=B0=D1=82=D0=B8=D0=B5=20-=20?= =?UTF-8?q?=D0=98=D0=BD=D0=B4=D0=B5=D0=BA=D1=81=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Homework/Индексы и сжатие - Индексы.sql | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 dsolovianov/clickhouse/Homework/Индексы и сжатие - Индексы.sql diff --git a/dsolovianov/clickhouse/Homework/Индексы и сжатие - Индексы.sql b/dsolovianov/clickhouse/Homework/Индексы и сжатие - Индексы.sql new file mode 100644 index 0000000..9332b35 --- /dev/null +++ b/dsolovianov/clickhouse/Homework/Индексы и сжатие - Индексы.sql @@ -0,0 +1,166 @@ +-- Индексы и сжатие - Индексы -- + +-- #1 +/* +3. Посмотри, сколько блоков было пропущено (в `system.query_log`, `rows_read`, `rows`). +Не посмотрю, так как нет доступа system.query_log, rows_read, rows (ACCESS_DENIED) +4. Что будет, если `ORDER BY log_id`, а не `ts`? +ORDER BY log_id → данные физически отсортированы по log_id. Значения ts расположены хаотично относительно физической сортировки. +Индекс minmax по ts будет почти бесполезен. Minmax индекс будет иметь широкие диапазоны +*/ + +DROP TABLE IF EXISTS dsolovianov.logs ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.logs +ON CLUSTER clickhouse_cluster +( + log_id UInt64, + ts DateTime +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/logs', + '{replica}' +) +ORDER BY ts +PARTITION BY toYYYYMM(ts) +PRIMARY KEY (ts); + +INSERT INTO dsolovianov.logs (log_id, ts) VALUES +(1, '2024-06-01 10:00:00'), +(2, '2024-06-01 11:00:00'), +(3, '2024-06-02 12:00:00'), +(4, '2024-06-03 13:00:00'), +(5, '2024-06-04 14:00:00'); + +-- 1. Добавляем minmax индекс: +ALTER TABLE dsolovianov.logs ADD INDEX idx_ts ts TYPE minmax GRANULARITY 2; + +-- 2. Сделай запрос: `SELECT * FROM logs WHERE ts BETWEEN '2024-06-02' AND '2024-06-03'` +SELECT * +FROM dsolovianov.logs +WHERE ts + BETWEEN '2024-06-02' AND '2024-06-03'; + +-- Раз нет доступа, но можно предположить, что вот такой запрос сработает: +SELECT query, read_rows, result_rows +FROM system.query_log +WHERE query LIKE '%logs%' +ORDER BY event_time DESC +LIMIT 1; + + +-- #2 +/* +1. Создай таблицу с `ORDER BY id`, добавь индекс: + + ```sql + ALTER TABLE clicks ADD INDEX idx_country country TYPE set(1000) GRANULARITY 2; + ``` + + +3. Посмотри `EXPLAIN` — индекс используется? +Данные отсортированы по id, а не по country. Значения country распределены хаотически относительно физического порядка. +4. Как будет вести себя индекс, если `country` имеет 10M уникальных значений? +Будет создано 10M партиций, что убьёт производительность. +**/ +DROP TABLE IF EXISTS dsolovianov.clicks ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.clicks +ON CLUSTER clickhouse_cluster +( + id UInt64, + country String +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/clicks', + '{replica}' +) +ORDER BY id +PARTITION BY country +PRIMARY KEY (id); + +INSERT INTO dsolovianov.clicks (id, country) VALUES +(1, 'RU'), +(2, 'US'), +(3, 'RU'), +(4, 'DE'), +(5, 'RU'); + +ALTER TABLE dsolovianov.clicks ON CLUSTER clickhouse_cluster +ADD INDEX idx_country country TYPE set(1000) GRANULARITY 2; + +-- 2. Выполни запрос `SELECT * FROM clicks WHERE country = 'RU'`. +EXPLAIN indexes = 1 +SELECT * FROM dsolovianov.clicks WHERE country = 'RU'; + +EXPLAIN +SELECT * FROM dsolovianov.clicks WHERE country = 'RU'; + +/* +Expression ((Project names + Projection)) + Expression ((WHERE + Change column names to column identifiers)) + ReadFromMergeTree (dsolovianov.clicks) + Indexes: + MinMax + Keys: + country + Condition: (country in ['RU', 'RU']) + Parts: 1/3 + Granules: 1/3 + Partition + Keys: + country + Condition: (country in ['RU', 'RU']) + Parts: 1/1 + Granules: 1/1 + PrimaryKey + Condition: true + Parts: 1/1 + Granules: 1/1 + Skip + Name: idx_country + Description: set GRANULARITY 2 + Parts: 1/1 + Granules: 1/1 + Ranges: 1 + */ + +-- #3 + +DROP TABLE IF EXISTS dsolovianov.users ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.users +ON CLUSTER clickhouse_cluster +( + id UInt64, + email String +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/users', + '{replica}' +) +ORDER BY id +PRIMARY KEY (id); + +INSERT INTO dsolovianov.users (id, email) VALUES +(1, 'alice@mail.com'), +(2, 'bob@mail.com'), +(3, 'charlie@mail.com'), +(4, 'dave@mail.com'), +(5, 'eve@example.com'); + +ALTER TABLE dsolovianov.users ADD INDEX idx_email email TYPE bloom_filter(0.01) GRANULARITY 2; + +EXPLAIN indexes = 1 +SELECT * FROM users WHERE email = 'alice@mail.com'; +-- Bloom filter может пропустить некоторые гранулы, но не все, ибо данные не отсортированы по email и индексные блоки покрывают случайные email'ы + +EXPLAIN indexes = 1 +SELECT * FROM users WHERE email LIKE '%mail%'; + +EXPLAIN indexes = 1 +SELECT * FROM users WHERE email LIKE 'alice%'; +/* +Bloom filter не поддерживает частичные совпадения (LIKE '..%', LIKE '%..', LIKE '%..%'). Из-за этого ClickHouse не может пропустить гранулы. +Клику становится сложно вычислить хэш для проверки, если подходящих значений по LIKE будет больше одного. Нет гарантии, что данные на выходе будут корректные. +*/ \ No newline at end of file From c654840ffdbbc003bb92a186980c507ac90b9b8e Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 4 May 2026 09:15:50 +0400 Subject: [PATCH 26/48] =?UTF-8?q?=D0=98=D0=BD=D0=B4=D0=B5=D0=BA=D1=81?= =?UTF-8?q?=D1=8B=20=D0=B8=20=D1=81=D0=B6=D0=B0=D1=82=D0=B8=D0=B5=20-=20?= =?UTF-8?q?=D0=A1=D0=B6=D0=B0=D1=82=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Homework/Индексы и сжатие - Сжатие.sql | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 dsolovianov/clickhouse/Homework/Индексы и сжатие - Сжатие.sql diff --git a/dsolovianov/clickhouse/Homework/Индексы и сжатие - Сжатие.sql b/dsolovianov/clickhouse/Homework/Индексы и сжатие - Сжатие.sql new file mode 100644 index 0000000..ce28674 --- /dev/null +++ b/dsolovianov/clickhouse/Homework/Индексы и сжатие - Сжатие.sql @@ -0,0 +1,39 @@ +-- Индексы и сжатие - Сжатие -- + +-- #1 Создай таблицу logs с колонкой message CODEC(ZSTD(3)). +-- #2 Добавь created_at CODEC(Delta, ZSTD) — это улучшит хранение по времени. +DROP TABLE IF EXISTS dsolovianov.logs ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.logs +ON CLUSTER clickhouse_cluster +( + id UInt64, + level String, + message String CODEC(ZSTD(3)), + created_at DateTime CODEC(Delta, ZSTD) +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/logs', + '{replica}' +) +ORDER BY (created_at, id) +PARTITION BY toYYYYMM(created_at); + +INSERT INTO dsolovianov.logs (id, level, message, created_at) VALUES +(1, 'INFO', 'User logged in', '2024-07-01 10:00:00'), +(2, 'WARN', 'Request took too long', '2024-07-01 10:05:00'), +(3, 'ERROR', 'Unable to connect to server', '2024-07-01 10:10:00'); + +-- #3 Посмотри статистику сжатия: +SELECT + column, + compression_codec +FROM system.columns +WHERE table = 'logs'; + +-- Стата вот так выглядит: +column | compression_codec +id +level +message CODEC(ZSTD(3)) +created_at CODEC(Delta(4), ZSTD(1)) \ No newline at end of file From 3f4fe5f0157a28f2eb0288aba523ba3120677bee Mon Sep 17 00:00:00 2001 From: "valera.beretar" Date: Wed, 6 May 2026 22:31:35 +0300 Subject: [PATCH 27/48] add home work on ddl --- vberetar/postgresql/ddl.sql | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 vberetar/postgresql/ddl.sql diff --git a/vberetar/postgresql/ddl.sql b/vberetar/postgresql/ddl.sql new file mode 100644 index 0000000..19fd57f --- /dev/null +++ b/vberetar/postgresql/ddl.sql @@ -0,0 +1,39 @@ +CREATE TABLE users ( + id INT PRIMARY KEY NOT NULL, + name VARCHAR(100) NOT NULL, + age SMALLINT, + email VARCHAR(100), + country VARCHAR(50), + is_active BOOLEAN DEFAULT true, + created_at TIMESTAMPTZ NOT NULL +); +-- age - для возраста не нужны болшие числа +-- country - можно было бы использовать VARCHAR(2), я бы тут спросил у тимлида как будет удобней использовать поле) +-- created_at - нужно знать не только дату но и время создания/регистрации +-- id - если не прописать not null в primary key, то not null ставится автоматически? + +CREATE TABLE products ( + id INT PRIMARY KEY, + name VARCHAR(100) NOT NULL, + category VARCHAR(50), + price DECIMAL(10, 2) NOT NULL, + in_stock BOOLEAN +); + +CREATE TABLE orders( + id INT PRIMARY KEY, + user_id INT, + order_date TIMESTAMPTZ NOT NULL, + status VARCHAR(20), + FOREING KEY (user_id) REFERENCES users(id) +); +-- status - лучше прописать словами статус, так понятней будет. Я бы сюда поставил ENUM + +CREATE TABLE order_items( + order_id INT, + product_id INT, + quantity INT NOT NULL, + price_at_purchase DECIMAL(10, 2) NOT NULL, + FOREING KEY (order_id) REFERENCES orders(id), + FOREING KEY (product_id) REFERENCES products(id) +); \ No newline at end of file From 06ad98f4faf3d7ad6812f0b5661247f12edae62c Mon Sep 17 00:00:00 2001 From: "valera.beretar" Date: Fri, 8 May 2026 11:46:36 +0300 Subject: [PATCH 28/48] fix columns in tables --- vberetar/postgresql/ddl.sql | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/vberetar/postgresql/ddl.sql b/vberetar/postgresql/ddl.sql index 19fd57f..ce86724 100644 --- a/vberetar/postgresql/ddl.sql +++ b/vberetar/postgresql/ddl.sql @@ -1,8 +1,8 @@ CREATE TABLE users ( - id INT PRIMARY KEY NOT NULL, + id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, name VARCHAR(100) NOT NULL, - age SMALLINT, - email VARCHAR(100), + age SMALLINT CHECK (age > 0), + email VARCHAR(100) NOT NULL UNIQUE, country VARCHAR(50), is_active BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL @@ -13,27 +13,26 @@ CREATE TABLE users ( -- id - если не прописать not null в primary key, то not null ставится автоматически? CREATE TABLE products ( - id INT PRIMARY KEY, + id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, name VARCHAR(100) NOT NULL, category VARCHAR(50), price DECIMAL(10, 2) NOT NULL, - in_stock BOOLEAN + in_stock BOOLEAN DEFAULT true, ); CREATE TABLE orders( - id INT PRIMARY KEY, + id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, user_id INT, order_date TIMESTAMPTZ NOT NULL, status VARCHAR(20), - FOREING KEY (user_id) REFERENCES users(id) + FOREIGN KEY (user_id) REFERENCES users(id) ); -- status - лучше прописать словами статус, так понятней будет. Я бы сюда поставил ENUM CREATE TABLE order_items( - order_id INT, - product_id INT, + order_id INT NOT NULL, + product_id INT NOT NULL, quantity INT NOT NULL, price_at_purchase DECIMAL(10, 2) NOT NULL, - FOREING KEY (order_id) REFERENCES orders(id), - FOREING KEY (product_id) REFERENCES products(id) + PRIMARY KEY (order_id, product_id) ); \ No newline at end of file From a3342be276339ca64133bd07969e8488f67aacd8 Mon Sep 17 00:00:00 2001 From: "valera.beretar" Date: Fri, 8 May 2026 11:50:55 +0300 Subject: [PATCH 29/48] add DML home work --- vberetar/postgresql/dml.sql | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 vberetar/postgresql/dml.sql diff --git a/vberetar/postgresql/dml.sql b/vberetar/postgresql/dml.sql new file mode 100644 index 0000000..8829f99 --- /dev/null +++ b/vberetar/postgresql/dml.sql @@ -0,0 +1,42 @@ +INSERT INTO users (id, name, age, email, country, is_active, created_at) +VALUES (1, 'Alice', 25, 'alice@example.com', 'US', true, '2024-01-10 10:00:00'), + (2, 'Bob', 30, 'bob@example.com', 'UK', true, '2024-02-05 09:30:00'), + (3, 'Carol', 27, 'carol@example.com', 'US', false, '2024-03-01 15:20:00'), + (4, 'Diana', 22, 'diana@GMAIL.com', 'US', true, '2024-01-12 08:15:00'), + (5, 'Evan', 35, 'EVAN@example.com', 'UK', true, '2024-01-18 19:40:00'), + (6, 'Farida', 29, 'farida@example.com', 'KZ', true, '2024-02-20 11:05:00'), + (7, 'George', 31, 'george+test@example.com', 'US', true, '2024-03-05 16:45:00'), + (8, 'Helen', 24, NULL, 'UK', false, '2024-03-06 08:20:00'), + (9, 'Ivan', 26, 'ivan@example.com', 'RU', true, '2024-01-11 14:30:00'), + (10, 'Julia', 28, 'julia@example.com', 'US', true, '2024-03-07 18:05:00'); + +INSERT INTO products (id, name, category, price, in_stock) +VALUES (1, 'iPhone 15', 'Электроника', 80000, true), + (2, 'Kindle', 'Электроника', 15000, true), + (3, 'Кроссовки Nike', 'Одежда', 9000, true), + (4, 'Кроссовки NoName', 'Одежда', 3000, false), + (5, 'Наушники Pro', 'Электроника', 12000, true), + (6, 'Фитнес‑браслет', 'Гаджеты', 6000, true), + (7, 'Подарочная карта', 'Сервисы', 1000, true); + +INSERT INTO orders (id, user_id, order_date, status) +VALUES (1, 1, '2025-01-10 12:00:00', 'paid'), + (2, 3, '2025-01-12 09:30:00', 'cancelled'), + (3, 1, '2025-01-15 18:20:00', 'paid'), + (4, 2, '2025-01-20 11:05:00', 'created'), + (5, 4, '2025-02-01 17:45:00', 'paid'), + (6, 5, '2025-02-10 10:10:00', 'refunded'), + (7, 7, '2025-03-01 09:00:00', 'paid'), + (8, 9, '2025-03-05 19:30:00', 'paid'); + +INSERT INTO order_items (order_id, product_id, quantity, price_at_purchase) +VALUES (1, 1, 1, 78000), + (1, 3, 2, 8500), + (2, 2, 1, 14000), + (3, 5, 1, 11000), + (3, 7, 1, 1000), + (4, 2, 1, 15000), + (5, 6, 1, 6000), + (6, 1, 1, 82000), + (7, 3, 1, 9000), + (8, 4, 2, 2800); From 4ffe6cac39463fa423246172f0df747f0b481817 Mon Sep 17 00:00:00 2001 From: "valera.beretar" Date: Sun, 10 May 2026 21:57:26 +0300 Subject: [PATCH 30/48] fix query on dml.sql --- vberetar/postgresql/dml.sql | 55 ++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/vberetar/postgresql/dml.sql b/vberetar/postgresql/dml.sql index 8829f99..24e8d83 100644 --- a/vberetar/postgresql/dml.sql +++ b/vberetar/postgresql/dml.sql @@ -1,33 +1,32 @@ -INSERT INTO users (id, name, age, email, country, is_active, created_at) -VALUES (1, 'Alice', 25, 'alice@example.com', 'US', true, '2024-01-10 10:00:00'), - (2, 'Bob', 30, 'bob@example.com', 'UK', true, '2024-02-05 09:30:00'), - (3, 'Carol', 27, 'carol@example.com', 'US', false, '2024-03-01 15:20:00'), - (4, 'Diana', 22, 'diana@GMAIL.com', 'US', true, '2024-01-12 08:15:00'), - (5, 'Evan', 35, 'EVAN@example.com', 'UK', true, '2024-01-18 19:40:00'), - (6, 'Farida', 29, 'farida@example.com', 'KZ', true, '2024-02-20 11:05:00'), - (7, 'George', 31, 'george+test@example.com', 'US', true, '2024-03-05 16:45:00'), - (8, 'Helen', 24, NULL, 'UK', false, '2024-03-06 08:20:00'), - (9, 'Ivan', 26, 'ivan@example.com', 'RU', true, '2024-01-11 14:30:00'), - (10, 'Julia', 28, 'julia@example.com', 'US', true, '2024-03-07 18:05:00'); +INSERT INTO users (name, age, email, country, is_active, created_at) +VALUES ('Alice', 25, LOWER('alice@example.com'), 'US', true, '2024-01-10 10:00:00'), + ('Bob', 30, LOWER('bob@example.com'), 'UK', true, '2024-02-05 09:30:00'), + ('Carol', 27, LOWER('carol@example.com'), 'US', false, '2024-03-01 15:20:00'), + ('Diana', 22, LOWER('diana@GMAIL.com'), 'US', true, '2024-01-12 08:15:00'), + ('Evan', 35, LOWER('EVAN@example.com'), 'UK', true, '2024-01-18 19:40:00'), + ('Farida', 29, LOWER('farida@example.com'), 'KZ', true, '2024-02-20 11:05:00'), + ('George', 31, LOWER('george+test@example.com'), 'US', true, '2024-03-05 16:45:00'), + ('Ivan', 26, LOWER('ivan@example.com'), 'RU', true, '2024-01-11 14:30:00'), + ('Julia', 28, LOWER('julia@example.com'), 'US', true, '2024-03-07 18:05:00'); -INSERT INTO products (id, name, category, price, in_stock) -VALUES (1, 'iPhone 15', 'Электроника', 80000, true), - (2, 'Kindle', 'Электроника', 15000, true), - (3, 'Кроссовки Nike', 'Одежда', 9000, true), - (4, 'Кроссовки NoName', 'Одежда', 3000, false), - (5, 'Наушники Pro', 'Электроника', 12000, true), - (6, 'Фитнес‑браслет', 'Гаджеты', 6000, true), - (7, 'Подарочная карта', 'Сервисы', 1000, true); +INSERT INTO products (name, category, price, in_stock) +VALUES ('iPhone 15', 'Электроника', 80000, true), + ('Kindle', 'Электроника', 15000, true), + ('Кроссовки Nike', 'Одежда', 9000, true), + ('Кроссовки NoName', 'Одежда', 3000, false), + ('Наушники Pro', 'Электроника', 12000, true), + ('Фитнес‑браслет', 'Гаджеты', 6000, true), + ('Подарочная карта', 'Сервисы', 1000, true); -INSERT INTO orders (id, user_id, order_date, status) -VALUES (1, 1, '2025-01-10 12:00:00', 'paid'), - (2, 3, '2025-01-12 09:30:00', 'cancelled'), - (3, 1, '2025-01-15 18:20:00', 'paid'), - (4, 2, '2025-01-20 11:05:00', 'created'), - (5, 4, '2025-02-01 17:45:00', 'paid'), - (6, 5, '2025-02-10 10:10:00', 'refunded'), - (7, 7, '2025-03-01 09:00:00', 'paid'), - (8, 9, '2025-03-05 19:30:00', 'paid'); +INSERT INTO orders (user_id, order_date, status) +VALUES (1, '2025-01-10 12:00:00', 'paid'), + (3, '2025-01-12 09:30:00', 'cancelled'), + (1, '2025-01-15 18:20:00', 'paid'), + (2, '2025-01-20 11:05:00', 'created'), + (4, '2025-02-01 17:45:00', 'paid'), + (5, '2025-02-10 10:10:00', 'refunded'), + (7, '2025-03-01 09:00:00', 'paid'), + (9, '2025-03-05 19:30:00', 'paid'); INSERT INTO order_items (order_id, product_id, quantity, price_at_purchase) VALUES (1, 1, 1, 78000), From d280456d0919ddc8f64382d0c7b16846ab8cb38b Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 11 May 2026 04:21:02 +0400 Subject: [PATCH 31/48] =?UTF-8?q?=D0=BF=D0=B5=D1=82-=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BA=D1=82=20=D0=BF=D0=BE=D0=BB=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Этап 1. Загрузка тестовых данных.sql | 90 +++++++++ .../Этап 2. Создание витринных таблиц.sql | 186 ++++++++++++++++++ .../Pet-Project/Этап 3. Анализ и запросы.sql | 88 +++++++++ .../Этап 4. Тестирование и валидация.sql | 13 ++ 4 files changed, 377 insertions(+) create mode 100644 dsolovianov/clickhouse/Pet-Project/Этап 1. Загрузка тестовых данных.sql create mode 100644 dsolovianov/clickhouse/Pet-Project/Этап 2. Создание витринных таблиц.sql create mode 100644 dsolovianov/clickhouse/Pet-Project/Этап 3. Анализ и запросы.sql create mode 100644 dsolovianov/clickhouse/Pet-Project/Этап 4. Тестирование и валидация.sql diff --git a/dsolovianov/clickhouse/Pet-Project/Этап 1. Загрузка тестовых данных.sql b/dsolovianov/clickhouse/Pet-Project/Этап 1. Загрузка тестовых данных.sql new file mode 100644 index 0000000..167607d --- /dev/null +++ b/dsolovianov/clickhouse/Pet-Project/Этап 1. Загрузка тестовых данных.sql @@ -0,0 +1,90 @@ +DROP TABLE IF EXISTS dsolovianov.core_fact_lesson_views ON CLUSTER clickhouse_cluster SYNC; +DROP TABLE IF EXISTS dsolovianov.core_dim_user ON CLUSTER clickhouse_cluster SYNC; +DROP TABLE IF EXISTS dsolovianov.core_dim_course ON CLUSTER clickhouse_cluster SYNC; +DROP TABLE IF EXISTS dsolovianov.core_dim_lesson ON CLUSTER clickhouse_cluster SYNC; +DROP TABLE IF EXISTS dsolovianov.core_dim_date ON CLUSTER clickhouse_cluster SYNC; +DROP TABLE IF EXISTS dsolovianov.core_enrollments ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.core_dim_user +ON CLUSTER clickhouse_cluster +( + user_id Int32, + name String, + age Int32, + email String, + registration_date Date +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/core_dim_user', + '{replica}' +) +ORDER BY user_id; + +CREATE TABLE dsolovianov.core_dim_course +ON CLUSTER clickhouse_cluster +( + course_id Int32, + title String, + category String +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/core_dim_course', + '{replica}' +) +ORDER BY course_id; + +CREATE TABLE dsolovianov.core_dim_lesson +ON CLUSTER clickhouse_cluster +( + lesson_id Int32, + title String, + duration_min Int32, + course_id Int32 +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/core_dim_lesson', + '{replica}' +) +ORDER BY lesson_id; + +CREATE TABLE dsolovianov.core_dim_date +ON CLUSTER clickhouse_cluster +( + date Date, + year Int32, + month Int32, + day Int32, + weekday String +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/core_dim_date', + '{replica}' +) +ORDER BY date; + +CREATE TABLE dsolovianov.core_enrollments +ON CLUSTER clickhouse_cluster +( + user_id Int32, + course_id Int32, + enrolled_at DateTime64(3) +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/core_enrollments', + '{replica}' +) +ORDER BY user_id; + +CREATE TABLE dsolovianov.core_fact_lesson_views +ON CLUSTER clickhouse_cluster +( + user_id Int32, + lesson_id Int32, + course_id Int32, + viewed_at DateTime64(3) +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/core_fact_lesson_views', + '{replica}' +) +ORDER BY user_id; \ No newline at end of file diff --git a/dsolovianov/clickhouse/Pet-Project/Этап 2. Создание витринных таблиц.sql b/dsolovianov/clickhouse/Pet-Project/Этап 2. Создание витринных таблиц.sql new file mode 100644 index 0000000..e2dc606 --- /dev/null +++ b/dsolovianov/clickhouse/Pet-Project/Этап 2. Создание витринных таблиц.sql @@ -0,0 +1,186 @@ +-- Этап 2. Создание витринных таблиц -- + +-- Витрина lesson_popularity_summary +DROP TABLE IF EXISTS dsolovianov.lesson_popularity_summary ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.lesson_popularity_summary ON CLUSTER clickhouse_cluster ( + lesson_id UInt32, + lesson_title String, + course_id UInt32, + course_title String, + total_views UInt64, + unique_users UInt64, + first_view DateTime, + last_view DateTime +) ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/lesson_popularity_summary', + '{replica}' +) +ORDER BY (course_id, lesson_id); + +CREATE MATERIALIZED VIEW dsolovianov.lesson_popularity_summary_mv ON CLUSTER clickhouse_cluster +TO dsolovianov.lesson_popularity_summary +AS +SELECT + l.lesson_id AS lesson_id, + l.title AS lesson_title, + l.course_id AS course_id, + c.title AS course_title, + COUNT(v.viewed_at) AS total_views, + COUNT(DISTINCT v.user_id) AS unique_users, + MIN(v.viewed_at) AS first_view, + MAX(v.viewed_at) AS last_view +FROM dsolovianov.core_fact_lesson_views v +LEFT JOIN dsolovianov.core_dim_lesson l ON v.lesson_id = l.lesson_id +LEFT JOIN dsolovianov.core_dim_course c ON l.course_id = c.course_id +GROUP BY l.lesson_id, l.title, l.course_id, c.title; + +INSERT INTO dsolovianov.lesson_popularity_summary +SELECT + l.lesson_id AS lesson_id, + l.title AS lesson_title, + l.course_id AS course_id, + c.title AS course_title, + COUNT(v.viewed_at) AS total_views, + COUNT(DISTINCT v.user_id) AS unique_users, + MIN(v.viewed_at) AS first_view, + MAX(v.viewed_at) AS last_view +FROM dsolovianov.core_dim_lesson l +JOIN dsolovianov.core_dim_course c ON l.course_id = c.course_id +LEFT JOIN dsolovianov.core_fact_lesson_views v ON l.lesson_id = v.lesson_id +GROUP BY l.lesson_id, l.title, l.course_id, c.title; + +-- Витрину inactive_users_summary + +DROP TABLE IF EXISTS dsolovianov.inactive_users_summary ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.inactive_users_summary ON CLUSTER clickhouse_cluster ( + user_id UInt32, + name String, + email String, + age UInt8, + registered_courses_count UInt32, + registration_date Date +) ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/inactive_users_summary', + '{replica}' +) +ORDER BY user_id; + +CREATE MATERIALIZED VIEW dsolovianov.inactive_users_summary_mv ON CLUSTER clickhouse_cluster +TO dsolovianov.inactive_users_summary +AS +SELECT + u.user_id AS user_id, + u.name AS name, + u.email AS email, + u.age AS age, + COUNT(DISTINCT e.course_id) AS registered_courses_count, + u.registration_date AS registration_date +FROM dsolovianov.core_dim_user u +LEFT JOIN dsolovianov.core_enrollments e ON u.user_id = e.user_id +WHERE u.user_id NOT IN (SELECT DISTINCT user_id FROM dsolovianov.core_fact_lesson_views) +GROUP BY u.user_id, u.name, u.email, u.age, u.registration_date; + +INSERT INTO dsolovianov.inactive_users_summary +SELECT + u.user_id AS user_id, + u.name AS name, + u.email AS email, + u.age AS age, + COUNT(DISTINCT e.course_id) AS registered_courses_count, + u.registration_date AS registration_date +FROM dsolovianov.core_dim_user u +LEFT JOIN dsolovianov.core_enrollments e ON u.user_id = e.user_id +WHERE u.user_id NOT IN (SELECT DISTINCT user_id FROM dsolovianov.core_fact_lesson_views) +GROUP BY u.user_id, u.name, u.email, u.age, u.registration_date; + +-- Витрина course_completion_rate + +DROP TABLE IF EXISTS dsolovianov.course_completion_rate ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.course_completion_rate ON CLUSTER clickhouse_cluster ( + user_id UInt32, + user_name String, + course_id UInt32, + course_title String, + lessons_in_course UInt32, + lessons_viewed UInt32, + completion_rate Float32 +) ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/course_completion_rate', + '{replica}' +) +ORDER BY (user_id, course_id); + +DROP TABLE IF EXISTS dsolovianov.course_completion_rate_mv ON CLUSTER clickhouse_cluster SYNC; + +CREATE MATERIALIZED VIEW dsolovianov.course_completion_rate_mv ON CLUSTER clickhouse_cluster +TO dsolovianov.course_completion_rate +AS +SELECT + e.user_id AS user_id, + u.name AS user_name, + e.course_id AS course_id, + c.title AS course_title, + ( + SELECT COUNT(*) + FROM dsolovianov.core_dim_lesson l + WHERE l.course_id = e.course_id + ) AS lessons_in_course, + ( + SELECT COUNT(DISTINCT v.lesson_id) + FROM dsolovianov.core_fact_lesson_views v + JOIN dsolovianov.core_dim_lesson l ON v.lesson_id = l.lesson_id + WHERE v.user_id = e.user_id AND l.course_id = e.course_id + ) AS lessons_viewed, + ( + SELECT COUNT(DISTINCT v.lesson_id) + FROM dsolovianov.core_fact_lesson_views v + JOIN dsolovianov.core_dim_lesson l ON v.lesson_id = l.lesson_id + WHERE v.user_id = e.user_id AND l.course_id = e.course_id + ) / ( + SELECT COUNT(*) + FROM dsolovianov.core_dim_lesson l + WHERE l.course_id = e.course_id + ) AS completion_rate +FROM dsolovianov.core_enrollments e +JOIN dsolovianov.core_dim_user u ON e.user_id = u.user_id +JOIN dsolovianov.core_dim_course c ON e.course_id = c.course_id +GROUP BY e.user_id, u.name, e.course_id, c.title; + +INSERT INTO dsolovianov.course_completion_rate +SELECT + e.user_id AS user_id, + u.name AS user_name, + e.course_id AS course_id, + c.title AS course_title, + ( + SELECT COUNT(*) + FROM dsolovianov.core_dim_lesson l + WHERE l.course_id = e.course_id + ) AS lessons_in_course, + COALESCE( + ( + SELECT COUNT(DISTINCT v.lesson_id) + FROM dsolovianov.core_fact_lesson_views v + JOIN dsolovianov.core_dim_lesson l ON v.lesson_id = l.lesson_id + WHERE v.user_id = e.user_id AND l.course_id = e.course_id + ), 0 + ) AS lessons_viewed, + COALESCE( + ( + SELECT COUNT(DISTINCT v.lesson_id) + FROM dsolovianov.core_fact_lesson_views v + JOIN dsolovianov.core_dim_lesson l ON v.lesson_id = l.lesson_id + WHERE v.user_id = e.user_id AND l.course_id = e.course_id + ), 0 + ) / ( + SELECT COUNT(*) + FROM dsolovianov.core_dim_lesson l + WHERE l.course_id = e.course_id + ) AS completion_rate +FROM dsolovianov.core_enrollments e +JOIN dsolovianov.core_dim_user u ON e.user_id = u.user_id +JOIN dsolovianov.core_dim_course c ON e.course_id = c.course_id +GROUP BY e.user_id, u.name, e.course_id, c.title; diff --git a/dsolovianov/clickhouse/Pet-Project/Этап 3. Анализ и запросы.sql b/dsolovianov/clickhouse/Pet-Project/Этап 3. Анализ и запросы.sql new file mode 100644 index 0000000..6550e5b --- /dev/null +++ b/dsolovianov/clickhouse/Pet-Project/Этап 3. Анализ и запросы.sql @@ -0,0 +1,88 @@ +-- Этап 3. Анализ и запросы - Напиши SQL-запросы к витринам -- Напиши свои вариации для практики-- +-- Топ-5 самых просматриваемых уроков + +SELECT + lesson_title, + course_title, + total_views +FROM lesson_popularity_summary +ORDER BY total_views DESC +LIMIT 5; + +-- Неактивные пользователи, записавшиеся на курсы + +SELECT + name, + email, + registered_courses_count +FROM inactive_users_summary +WHERE registered_courses_count > 0 +ORDER BY registration_date DESC; + +-- Курсы с самым высоким процентом завершения + +SELECT + course_title, + AVG(completion_rate) AS avg_completion +FROM course_completion_rate +GROUP BY course_title +ORDER BY avg_completion DESC +LIMIT 5; + +-- Мои вариации -- + +-- Среднее количество учеников на урок по каждому курсу + +SELECT + course_title, + ROUND(AVG(unique_users), 2) AS avg_users_lesson, + SUM(total_views) AS total_course_views +FROM dsolovianov.lesson_popularity_summary +GROUP BY course_title +ORDER BY avg_users_lesson DESC; + +-- Возрастное распределение неактивных пользователей + +SELECT + CASE + WHEN age < 25 THEN 'до 25' + WHEN age BETWEEN 25 AND 30 THEN '25-30' + WHEN age BETWEEN 31 AND 35 THEN '31-35' + ELSE '35+' + END AS age_group, + COUNT(*) AS inactive_users_count, + AVG(registered_courses_count) AS avg_courses_enrolled +FROM dsolovianov.inactive_users_summary +GROUP BY age_group +ORDER BY age_group; + +-- Пользователи, которые начали, но не закончили курс (completion_rate между 0 и 1) + +SELECT + user_name, + course_title, + lessons_viewed, + lessons_in_course, + ROUND(completion_rate * 100, 0) AS no_completion, + (lessons_in_course - lessons_viewed) AS remaining_lessons +FROM dsolovianov.course_completion_rate +WHERE completion_rate BETWEEN 0.01 AND 0.99 +ORDER BY completion_rate DESC, user_name; + +-- Прогресс каждого пользователя по курсам (с указанием статуса) + +SELECT + user_name, + course_title, + lessons_viewed, + lessons_in_course, + ROUND(completion_rate * 100, 0) AS progress_percent, + CASE + WHEN completion_rate = 1.0 THEN 'Пройден' + WHEN completion_rate = 0 THEN 'Не начат' + WHEN completion_rate >= 0.5 THEN 'В процессе (>50%)' + ELSE 'В процессе (<50%)' + END AS status +FROM dsolovianov.course_completion_rate +ORDER BY user_name, completion_rate DESC; + diff --git a/dsolovianov/clickhouse/Pet-Project/Этап 4. Тестирование и валидация.sql b/dsolovianov/clickhouse/Pet-Project/Этап 4. Тестирование и валидация.sql new file mode 100644 index 0000000..f053160 --- /dev/null +++ b/dsolovianov/clickhouse/Pet-Project/Этап 4. Тестирование и валидация.sql @@ -0,0 +1,13 @@ +-- Этап 4. Тестирование и валидация -- + +/* +### **Задание 6: Сравни данные с Greenplum** + +1. Выбери 2–3 значения из таблиц `_summary_source` в Greenplum +2. Сравни с ClickHouse-результатами: + - Совпадает ли `SUM`, `AVG`, `MIN`, `MAX` + - Проверяй `NULL`, `0`, округления +3. Напиши мини-отчёт: **"где совпадает, где нет, почему"** +*/ + +-- Ничего не понятно по этому этапу. У меня в GP нет таблиц "_summary_source" From 0f63e2135317f1e3b37f043769c246872b360fdd Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 11 May 2026 06:50:16 +0400 Subject: [PATCH 32/48] DDL, DML, Basic, Filter --- dsolovianov/postgresql/DDL.sql | 32 +++++++ dsolovianov/postgresql/DML.sql | 59 ++++++++++++ dsolovianov/postgresql/Базовый SQL.sql | 89 +++++++++++++++++ dsolovianov/postgresql/Фильтрация.sql | 126 +++++++++++++++++++++++++ 4 files changed, 306 insertions(+) create mode 100644 dsolovianov/postgresql/DDL.sql create mode 100644 dsolovianov/postgresql/DML.sql create mode 100644 dsolovianov/postgresql/Базовый SQL.sql create mode 100644 dsolovianov/postgresql/Фильтрация.sql diff --git a/dsolovianov/postgresql/DDL.sql b/dsolovianov/postgresql/DDL.sql new file mode 100644 index 0000000..18d5050 --- /dev/null +++ b/dsolovianov/postgresql/DDL.sql @@ -0,0 +1,32 @@ +CREATE TABLE dsolovianov.users ( + id INT GENERATED ALWAYS AS IDENTITY NOT NULL, + name VARCHAR(100) NOT NULL, + age INT, + email VARCHAR(100), + country VARCHAR(100), + is_active BOOLEAN, + created_at TIMESTAMPTZ NOT NULL +); + +CREATE TABLE dsolovianov.products ( + id INT GENERATED ALWAYS AS IDENTITY NOT NULL, + name VARCHAR(100) NOT NULL, + category VARCHAR(50), + price DECIMAL(10,2) NOT NULL, + in_stock BOOLEAN + ); + +CREATE TABLE dsolovianov.orders ( + id INT GENERATED ALWAYS AS IDENTITY NOT NULL, + user_id INT, + order_date TIMESTAMPTZ NOT NULL, + status VARCHAR(20) +); + +CREATE TABLE dsolovianov.order_items ( + order_id INT NOT NULL, + product_id INT NOT NULL, + quantity INT NOT NULL, + price_at_purchase DECIMAL(10,2) NOT NULL, + CONSTRAINT order_items_pk PRIMARY KEY (order_id, product_id) +); \ No newline at end of file diff --git a/dsolovianov/postgresql/DML.sql b/dsolovianov/postgresql/DML.sql new file mode 100644 index 0000000..ef18ac6 --- /dev/null +++ b/dsolovianov/postgresql/DML.sql @@ -0,0 +1,59 @@ +INSERT INTO dsolovianov.users (name, age, email, country, is_active, created_at) VALUES +('Alice', 25, 'alice@example.com', 'US', true, '2024-01-10 10:00:00+00'), +('Bob', 30, 'bob@example.com', 'UK', true, '2024-02-05 09:30:00+00'), +('Carol', 27, 'carol@example.com', 'US', false, '2024-03-01 15:20:00+00'), +('Diana', 22, 'diana@GMAIL.com', 'US', true, '2024-01-12 08:15:00+00'), +('Evan', 35, 'EVAN@example.com', 'UK', true, '2024-01-18 19:40:00+00'), +('Farida', 29, 'farida@example.com', 'KZ', true, '2024-02-20 11:05:00+00'), +('George', 31, 'george+test@example.com', 'US', true, '2024-03-05 16:45:00+00'), +('Helen', 24, NULL, 'UK', false, '2024-03-06 08:20:00+00'), +('Ivan', 26, 'ivan@example.com', 'RU', true, '2024-01-11 14:30:00+00'), +('Julia', 28, 'julia@example.com', 'US', true, '2024-03-07 18:05:00+00'); + +INSERT INTO dsolovianov.products (name, category, price, in_stock) VALUES +('iPhone 15', 'Электроника', 80000, true), +('Kindle', 'Электроника', 15000, true), +('Кроссовки Nike', 'Одежда', 9000, true), +('Кроссовки NoName', 'Одежда', 3000, false), +('Наушники Pro', 'Электроника', 12000, true), +('Фитнес-браслет', 'Гаджеты', 6000, true), +('Подарочная карта', 'Сервисы', 1000, true); + +INSERT INTO dsolovianov.orders (user_id, order_date, status) VALUES +(1, '2025-01-10 12:00:00+00', 'paid'), +(3, '2025-01-12 09:30:00+00', 'cancelled'), +(1, '2025-01-15 18:20:00+00', 'paid'), +(2, '2025-01-20 11:05:00+00', 'created'), +(4, '2025-02-01 17:45:00+00', 'paid'), +(5, '2025-02-10 10:10:00+00', 'refunded'), +(7, '2025-03-01 09:00:00+00', 'paid'), +(9, '2025-03-05 19:30:00+00', 'paid'); + +INSERT INTO dsolovianov.order_items (order_id, product_id, quantity, price_at_purchase) VALUES +-- Заказ #1: iPhone 15 (1 шт) + Наушники Pro (2 шт) +(1, 1, 1, 80000.00), +(1, 5, 2, 12000.00), + +-- Заказ #2 (cancelled): Kindle (1 шт) +(2, 2, 1, 15000.00), + +-- Заказ #3: Кроссовки Nike (2 шт) +(3, 3, 2, 9000.00), + +-- Заказ #4 (created): Фитнес-браслет (1 шт) +(4, 6, 1, 6000.00), + +-- Заказ #5: iPhone 15 (1 шт) + Подарочная карта (3 шт) +(5, 1, 1, 80000.00), +(5, 7, 3, 1000.00), + +-- Заказ #6 (refunded): Наушники Pro (1 шт) +(6, 5, 1, 12000.00), + +-- Заказ #7: Kindle (1 шт) + Фитнес-браслет (2 шт) +(7, 2, 1, 15000.00), +(7, 6, 2, 6000.00), + +-- Заказ #8: iPhone 15 (1 шт) + Кроссовки Nike (1 шт) +(8, 1, 1, 80000.00), +(8, 3, 1, 9000.00); \ No newline at end of file diff --git a/dsolovianov/postgresql/Базовый SQL.sql b/dsolovianov/postgresql/Базовый SQL.sql new file mode 100644 index 0000000..7cf2ef7 --- /dev/null +++ b/dsolovianov/postgresql/Базовый SQL.sql @@ -0,0 +1,89 @@ +/* +- Задание 1 — Спроектируй «карточку пользователя» + + Ты делаешь экран “Пользователи” в админке и решаешь, какие поля там важны. + + Работаем с таблицей **`users`** + + **✅ Требования:** + + 1. Напиши запрос, который вернёт в результате только столбцы: **`id`**, **`name`**, **`country`**, **`created_at`**, **`email`** + 2. Потом измени запрос так, чтобы: + - сначала отсортировать по **`created_at`** (новые сверху) + - потом по **`name`** по алфавиту внутри одной даты + +- Задание 2 — Сегментация по странам (с выбором) + + Маркетолог хочет понять, какая страна сейчас интереснее. + + Работаем с таблицей **`users`** + + **✅ Требования:** + + 1. Выбери страну **`US`**и напиши запрос, который: + - вернёт **`id`**, **`name`**, **`country`**; + - покажет только пользователей из выбранной страны; + - отсортирует их по имени. + 2. Напиши второй запрос, который вернёт пользователей из страны **`UK`**. + +- Задание 3 — Контакты для рассылки (думать про качество) + + Нужно сделать список e‑mail для рассылки так, чтобы его не стыдно было отдавать маркетологу. + + **✅ Требования:** + + 1. Напиши один запрос, который: + - вернёт только пользователей, у которых email **есть**; + - вернёт столбцы **`id`**, **`name`**, **`email`**; + - отсортирует их по имени. + 2. Напиши второй запрос, который подготовит «чистый» вид email: + - вернёт только **`email`** в нижнем регистре (как **`email_lower`**); + - уберёт дубликаты email (нужно использовать **`DISTINCT`**). + - Задание 4 — Новички и активность + + «Тебе нужно посмотреть, кто пришёл недавно и кого стоит “подогреть”.» + + **✅ Требования:** + + 1. Напиши запрос, который: + - выберет пользователей, зарегистрированных **после** даты, которую ты сам выберешь (например, **`2024‑01‑11`**); + - вернёт **`id`**, **`name`**, **`created_at`**; + - отсортирует по **`created_at`** от новых к старым. + 2. Ограничь результат так, чтобы увидеть только 3 самых новых пользователя. + 3. Измени запрос так, чтобы пропустить самого нового и показать следующих двух (используй **`LIMIT`** и **`OFFSET`**). +*/ +SELECT id, + name, + country, + created_at, + email +FROM dsolovianov.users +ORDER BY created_at DESC, name ASC; + +SELECT id, + name, + country +FROM dsolovianov.users +WHERE country LIKE 'US'; + +SELECT id, + name, + country +FROM dsolovianov.users +WHERE country LIKE 'UK'; + +SELECT id, + name, + email, + LOWER(email) AS email_lower +FROM dsolovianov.users +WHERE email IS NOT NULL +ORDER BY name; + +SELECT id, + name, + created_at +FROM dsolovianov.users +WHERE created_at > '2024-01-11' +ORDER BY created_at DESC +LIMIT 3 OFFSET 1; diff --git a/dsolovianov/postgresql/Фильтрация.sql b/dsolovianov/postgresql/Фильтрация.sql new file mode 100644 index 0000000..d928d61 --- /dev/null +++ b/dsolovianov/postgresql/Фильтрация.sql @@ -0,0 +1,126 @@ +/*INSERT INTO dsolovianov.products (name, category, price, in_stock) VALUES + ('Mi Band 7', 'smartwatch', 49.00, true), + ('Surface Pro', 'tablet', 1299.00, true), + ('iPhone 15', 'smartphone', 999.00, true), + ('Logitech MX Master', 'mouse', 120.00, true);*/ + +/* +- Задача 1 — Товары для продажи + + Ты настраиваешь главную витрину магазина. Нужно показывать только товары, которые сейчас реально готовы продавать. + + **✅ Условия:** + + - товар **в наличии** + - категория **НЕ smartwatch** + - цена **от 100 до 1300** + - отдельно хотим видеть цену: + - с наценкой 30% ( price + 30%) + - с «виртуальным НДС» 50% (price + 50%) + + **✅ Вывести:** + + - `name`, `category`, `price` + - `price_with_markup` = price + 30% + - `price_with_vat` = price + 50% + +- Задача 2 — Скидочная корзина: дешёвые или дорогие + + Нужно собрать товары под акцию + + **✅ Условия:** + + - участвуют товары с ценой **меньше 100** или **больше 1000** + - скидка 15% (price - 15%) + + **✅ Вывести:** + + - `name`, `price` + - `price_with_discount` = price - 15% + +- Задача 3 — Категории для рекламы + + Маркетолог просит товары только из нужных категорий: + + **✅ Условия:** + + - category в списке: `tablet`, `smartphone`, `mouse` + - цена **не меньше 100** + + **✅ Вывести:** + + - `id`, `name`, `category`, `price` + - сортировка по цене по убыванию +- Задача 4 — Убрать iPhone из выборки + + Собираем список товаров, **кроме iPhone**, чтобы сделать подборку “не Apple”. + + **✅ Условия:** + + - название **НЕ содержит** `iPhone` + + **✅ Вывести:** + + - `name`, `category`, `price` +- Задача 5 — Поиск товаров по названию + + Представь, что у пользователя есть строка поиска на сайте. Нужно сделать **2 запроса**, которые помогут искать товары по названию. + + - 1) Найти товары, где в названии есть `"pro"` (без учёта регистра) + + 📌 Условия: + + - поиск должен сработать на `pro`, `PRO`, `Pro` + - вывести: `name`, `category`, `price` + - 2) Найти товары, где в названии есть `"mx"` (без учёта регистра) + + 📌 Условия: + + - вывести: `name`, `category`, `price` + - отсортировать по `price DESC` +*/ + + +SELECT name, + category, + price, + (price * 0.30) + price AS price_with_markup, + (price * 0.50) + price AS price_with_vat +FROM dsolovianov.products +WHERE category NOT IN ('smartwatch') + AND (price >= 100 AND price <= 1300); + +SELECT name, + price, + price - (price * 0.15) AS price_with_discount +FROM dsolovianov.products +WHERE price < 100 OR price > 1000; + +SELECT id, + name, + category, + price +FROM dsolovianov.products +WHERE category IN ('tablet', 'smartphone', 'mouse') AND price >= 100 +ORDER BY price DESC; + +SELECT name, + category, + price +FROM dsolovianov.products +WHERE category NOT LIKE '%iPhone%'; + +SELECT id, + name, + category, + price +FROM dsolovianov.products +WHERE name ILIKE '%pro%'; + +SELECT id, + name, + category, + price +FROM dsolovianov.products +WHERE name ILIKE '%mx%'; + From cbdb54a36b623f204776329bf21be4a286d0f862 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 11 May 2026 07:02:07 +0400 Subject: [PATCH 33/48] fix postgres --- dsolovianov/postgresql/DDL.sql | 14 +++++++++----- dsolovianov/postgresql/Базовый SQL.sql | 6 ++++-- dsolovianov/postgresql/Фильтрация.sql | 6 ++---- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/dsolovianov/postgresql/DDL.sql b/dsolovianov/postgresql/DDL.sql index 18d5050..5d2cdd7 100644 --- a/dsolovianov/postgresql/DDL.sql +++ b/dsolovianov/postgresql/DDL.sql @@ -1,5 +1,5 @@ CREATE TABLE dsolovianov.users ( - id INT GENERATED ALWAYS AS IDENTITY NOT NULL, + id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name VARCHAR(100) NOT NULL, age INT, email VARCHAR(100), @@ -9,7 +9,7 @@ CREATE TABLE dsolovianov.users ( ); CREATE TABLE dsolovianov.products ( - id INT GENERATED ALWAYS AS IDENTITY NOT NULL, + id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name VARCHAR(100) NOT NULL, category VARCHAR(50), price DECIMAL(10,2) NOT NULL, @@ -17,7 +17,7 @@ CREATE TABLE dsolovianov.products ( ); CREATE TABLE dsolovianov.orders ( - id INT GENERATED ALWAYS AS IDENTITY NOT NULL, + id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, user_id INT, order_date TIMESTAMPTZ NOT NULL, status VARCHAR(20) @@ -26,7 +26,11 @@ CREATE TABLE dsolovianov.orders ( CREATE TABLE dsolovianov.order_items ( order_id INT NOT NULL, product_id INT NOT NULL, - quantity INT NOT NULL, - price_at_purchase DECIMAL(10,2) NOT NULL, + quantity INT NOT NULL CHECK (quantity > 0), + price_at_purchase DECIMAL(10,2) NOT NULL CHECK (price_at_purchase > 0), CONSTRAINT order_items_pk PRIMARY KEY (order_id, product_id) + CONSTRAINT order_items_order_fk + FOREIGN KEY (order_id) REFERENCES dsolovianov.orders(id), + CONSTRAINT order_items_product_fk + FOREIGN KEY (product_id) REFERENCES dsolovianov.products(id) ); \ No newline at end of file diff --git a/dsolovianov/postgresql/Базовый SQL.sql b/dsolovianov/postgresql/Базовый SQL.sql index 7cf2ef7..930f258 100644 --- a/dsolovianov/postgresql/Базовый SQL.sql +++ b/dsolovianov/postgresql/Базовый SQL.sql @@ -64,13 +64,15 @@ SELECT id, name, country FROM dsolovianov.users -WHERE country LIKE 'US'; +WHERE country LIKE 'US' +ORDER BY name; SELECT id, name, country FROM dsolovianov.users -WHERE country LIKE 'UK'; +WHERE country LIKE 'UK' +ORDER BY name; SELECT id, name, diff --git a/dsolovianov/postgresql/Фильтрация.sql b/dsolovianov/postgresql/Фильтрация.sql index d928d61..edf113a 100644 --- a/dsolovianov/postgresql/Фильтрация.sql +++ b/dsolovianov/postgresql/Фильтрация.sql @@ -110,15 +110,13 @@ SELECT name, FROM dsolovianov.products WHERE category NOT LIKE '%iPhone%'; -SELECT id, - name, +SELECT name, category, price FROM dsolovianov.products WHERE name ILIKE '%pro%'; -SELECT id, - name, +SELECT name, category, price FROM dsolovianov.products From 327bed019dac2a46eaa3b604170c939d742b079b Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 11 May 2026 07:04:28 +0400 Subject: [PATCH 34/48] fix ddl --- dsolovianov/postgresql/DDL.sql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dsolovianov/postgresql/DDL.sql b/dsolovianov/postgresql/DDL.sql index 5d2cdd7..033894c 100644 --- a/dsolovianov/postgresql/DDL.sql +++ b/dsolovianov/postgresql/DDL.sql @@ -32,5 +32,7 @@ CREATE TABLE dsolovianov.order_items ( CONSTRAINT order_items_order_fk FOREIGN KEY (order_id) REFERENCES dsolovianov.orders(id), CONSTRAINT order_items_product_fk - FOREIGN KEY (product_id) REFERENCES dsolovianov.products(id) + FOREIGN KEY (product_id) REFERENCES dsolovianov.products(id), + CONSTRAINT orders_user_fk + FOREIGN KEY (user_id) REFERENCES dsolovianov.users(id) ); \ No newline at end of file From 6fe1e7ceb525e7520d7796e66c0ff9fc91d2d463 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 11 May 2026 07:05:38 +0400 Subject: [PATCH 35/48] fix ddl v2 --- dsolovianov/postgresql/DDL.sql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dsolovianov/postgresql/DDL.sql b/dsolovianov/postgresql/DDL.sql index 033894c..c3a8393 100644 --- a/dsolovianov/postgresql/DDL.sql +++ b/dsolovianov/postgresql/DDL.sql @@ -21,6 +21,8 @@ CREATE TABLE dsolovianov.orders ( user_id INT, order_date TIMESTAMPTZ NOT NULL, status VARCHAR(20) + CONSTRAINT orders_user_fk + FOREIGN KEY (user_id) REFERENCES dsolovianov.users(id) ); CREATE TABLE dsolovianov.order_items ( @@ -32,7 +34,5 @@ CREATE TABLE dsolovianov.order_items ( CONSTRAINT order_items_order_fk FOREIGN KEY (order_id) REFERENCES dsolovianov.orders(id), CONSTRAINT order_items_product_fk - FOREIGN KEY (product_id) REFERENCES dsolovianov.products(id), - CONSTRAINT orders_user_fk - FOREIGN KEY (user_id) REFERENCES dsolovianov.users(id) + FOREIGN KEY (product_id) REFERENCES dsolovianov.products(id) ); \ No newline at end of file From 52481d3186855477e48c74aa2c2339626c13cedf Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 11 May 2026 07:06:15 +0400 Subject: [PATCH 36/48] fix ddl v3 --- dsolovianov/postgresql/DDL.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsolovianov/postgresql/DDL.sql b/dsolovianov/postgresql/DDL.sql index c3a8393..a578b7b 100644 --- a/dsolovianov/postgresql/DDL.sql +++ b/dsolovianov/postgresql/DDL.sql @@ -20,7 +20,7 @@ CREATE TABLE dsolovianov.orders ( id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, user_id INT, order_date TIMESTAMPTZ NOT NULL, - status VARCHAR(20) + status VARCHAR(20), CONSTRAINT orders_user_fk FOREIGN KEY (user_id) REFERENCES dsolovianov.users(id) ); From bfc54f9dcfa39cdcd433dbf06da22512f51a3a1c Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 11 May 2026 07:07:01 +0400 Subject: [PATCH 37/48] ddl v4 --- dsolovianov/postgresql/DDL.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsolovianov/postgresql/DDL.sql b/dsolovianov/postgresql/DDL.sql index a578b7b..0c7c3b1 100644 --- a/dsolovianov/postgresql/DDL.sql +++ b/dsolovianov/postgresql/DDL.sql @@ -30,7 +30,7 @@ CREATE TABLE dsolovianov.order_items ( product_id INT NOT NULL, quantity INT NOT NULL CHECK (quantity > 0), price_at_purchase DECIMAL(10,2) NOT NULL CHECK (price_at_purchase > 0), - CONSTRAINT order_items_pk PRIMARY KEY (order_id, product_id) + CONSTRAINT order_items_pk PRIMARY KEY (order_id, product_id), CONSTRAINT order_items_order_fk FOREIGN KEY (order_id) REFERENCES dsolovianov.orders(id), CONSTRAINT order_items_product_fk From 80023d6054076329ef5f3562a86a0ec7dfea62a3 Mon Sep 17 00:00:00 2001 From: "valera.beretar" Date: Wed, 13 May 2026 20:14:51 +0300 Subject: [PATCH 38/48] completed my homework - sql base --- vberetar/postgresql/sql_query.sql | 73 +++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 vberetar/postgresql/sql_query.sql diff --git a/vberetar/postgresql/sql_query.sql b/vberetar/postgresql/sql_query.sql new file mode 100644 index 0000000..a0681ba --- /dev/null +++ b/vberetar/postgresql/sql_query.sql @@ -0,0 +1,73 @@ +-- Задание 1 +SELECT id, name, country, created_at, email +FROM users +ORDER BY created_at DESC, name; + +-- Почему выбрал именно эти столбцы и зачем такая сортировка? +-- Ответ на вопрос: +-- Эти столбцы нужны для анализа пользователей, для тех же аналитиков. +-- Сортировка по дате и имени, я так предпологаю, нужня для удобства. + + +-- Задание 2 +-- Запрос 1 +SELECT id, name, country +FROM users +WHERE country = 'US' +ORDER BY name; + +-- Запрос 2 +SELECT id, name, country +FROM users +WHERE country = 'UK' +ORDER BY name; + +-- Какой из двух запросов маркетологу полезнее и почему? +-- Ответ на вопрос: +-- Я так понимаю маркетологу нужно понять какое кол-во пользователей в каждой из стран зарегестрировалось в приложении. +-- Возможно для понимания продвижения продукта и насколько успешна маркетинговая стратегия. И в дальнейшем её корректировка. + + +-- Задание 3 +-- Запрос 1 +SELECT id, name, email +FROM users +WHERE email IS NOT NULL -- я знаю что email и так должен быть NOT NULL по DDL, но на всякий прописал +ORDER BY name; + +-- Запрос 2 +SELECT DISTINCT LOWER(email) as email_lower +FROM users +WHERE email IS NOT NULL; + +-- Зачем вообще приводить email к одному регистру и убирать дубликаты на стороне базы? +-- Ответ на вопрос: +-- Приводить email к нижнему регистру необходимо для того чтобы небыло дубликатов почты. +-- После гугления я узнал что в почтовых адресах могут допускаться верхние регистры букв, только потом создать email с теми же буквами но в нижнем регистре нельзя будет, они будут считаться индентичными. +-- Получается несколько пользователей могут залогинится под одним и тем же email адресом но с разными регистрами. А такое нельзя допускать. +-- Для рассылки дубликаты нужно убирать что-бы не приходила рассылка дважды в один и тот же email. + +-- Задание 4 +-- Запрос 1 +SELECT id, name, created_at +FROM users +WHERE created_at > '2024-01-14' +ORDER BY created_at DESC; + +-- Запрос 2 +SELECT id, name, created_at +FROM users +WHERE created_at > '2024-01-14' +ORDER BY created_at DESC +LIMIT 3; + +-- Запрос 3 +SELECT id, name, created_at +FROM users +WHERE created_at > '2024-01-14' +ORDER BY created_at DESC +OFFSET 1 LIMIT 2; + +-- В каком реальном сценарии тебе пригодится OFFSET? +-- Ответ на вопрос: +-- Не знаю, возможно понадобится посмотреть несколько записей из середины списка. From 4240f34f24d1f6a642452a0ff885704fe527c92c Mon Sep 17 00:00:00 2001 From: "valera.beretar" Date: Sat, 16 May 2026 20:16:10 +0300 Subject: [PATCH 39/48] add home work on 'sql filters' --- vberetar/postgresql/sql_filters.sql | 56 +++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 vberetar/postgresql/sql_filters.sql diff --git a/vberetar/postgresql/sql_filters.sql b/vberetar/postgresql/sql_filters.sql new file mode 100644 index 0000000..423f131 --- /dev/null +++ b/vberetar/postgresql/sql_filters.sql @@ -0,0 +1,56 @@ +-- Задача 1 +SELECT name, category, price, + price * 1.3 AS price_with_markup, + price * 1.5 AS price_with_vat +FROM products +WHERE (price BETWEEN 100 AND 1300) + AND category NOT IN ('smartwatch') + AND in_stock = 'true'; + +-- Вопрос: +-- Что лучше читается BETWEEN 100 AND 1300 или price >= 100 AND price <= 1300 и почему? +-- Ответ: +-- Для меня BETWEEN 100 AND 1300 читается лучше, сразу понятен срез от 100 и 1300. + + +-- Задача 2 +SELECT name, price, + price * 0.85 AS price_with_discount +FROM products +WHERE (price < 100 OR price > 1000); + +-- Вопрос: +-- Почему важно явно писать скобки в условии с OR, даже если кажется, что и так понятно? +-- Ответ: +-- Потому что условие может не правильно отобразить результат, AND выполняется раньше OR. +-- Для надежности лучше скобками прописывать явно. + + +-- Задача 3 +SELECT id, name, category, price +FROM products +WHERE price >= 100 + AND category IN ('tablet', 'smartphone', 'mouse') +ORDER BY price DESC; + + +-- Задача 4 +SELECT name, category, price +FROM products +WHERE name NOT LIKE '%iPhone%'; + + +-- Задача 5 +SELECT name, category, price +FROM products +WHERE name ILIKE '%pro%'; + +SELECT name, category, price +FROM products +WHERE name ILIKE '%mx%' +ORDER BY price DESC; + +-- Вопрос: +-- В одном предложении объясни, почему для поисковой строки лучше ILIKE '%pro%', а не = 'Pro'. +-- Ответ: +-- В названии товаров могут быть буквы (в словах) с разными регистрами, при поиске клиенту можен не показать часть товаров только потому что слово выглядить так - PRO а не так - Pro. From f427cfe22e29f9935da2e7c684ce42f5c6a039d8 Mon Sep 17 00:00:00 2001 From: "valera.beretar" Date: Mon, 18 May 2026 11:55:15 +0300 Subject: [PATCH 40/48] fix WHERE in task 1 --- vberetar/postgresql/sql_filters.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vberetar/postgresql/sql_filters.sql b/vberetar/postgresql/sql_filters.sql index 423f131..74925dd 100644 --- a/vberetar/postgresql/sql_filters.sql +++ b/vberetar/postgresql/sql_filters.sql @@ -5,7 +5,7 @@ SELECT name, category, price, FROM products WHERE (price BETWEEN 100 AND 1300) AND category NOT IN ('smartwatch') - AND in_stock = 'true'; + AND in_stock = TRUE; -- Вопрос: -- Что лучше читается BETWEEN 100 AND 1300 или price >= 100 AND price <= 1300 и почему? From c2eacd2bde15422c0d22d6950e3c00e72ec2f226 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 18 May 2026 19:55:26 +0400 Subject: [PATCH 41/48] =?UTF-8?q?1.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=81=D0=BE=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B9=20?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=20=D0=B4=D0=BB=D1=8F=20course=5Fcomple?= =?UTF-8?q?tion=5Frate,=20=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20DROP=20TA?= =?UTF-8?q?BLE=20=D0=B4=D0=BB=D1=8F=20=D0=B2=D1=8C=D1=8E=D1=85,=20=D0=B8?= =?UTF-8?q?=D0=B7=D0=BC=D0=B5=D0=BD=D0=B8=D0=BB=20age=20UInt8=20=D0=BD?= =?UTF-8?q?=D0=B0=20UInt32=202.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=81=D1=85=D0=B5=D0=BC=D1=8B=20=D0=B2=20=D0=AD=D1=82?= =?UTF-8?q?=D0=B0=D0=BF=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Этап 2. Создание витринных таблиц.sql | 9 ++++++++- .../Pet-Project/Этап 3. Анализ и запросы.sql | 12 ++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/dsolovianov/clickhouse/Pet-Project/Этап 2. Создание витринных таблиц.sql b/dsolovianov/clickhouse/Pet-Project/Этап 2. Создание витринных таблиц.sql index e2dc606..8f6e555 100644 --- a/dsolovianov/clickhouse/Pet-Project/Этап 2. Создание витринных таблиц.sql +++ b/dsolovianov/clickhouse/Pet-Project/Этап 2. Создание витринных таблиц.sql @@ -18,6 +18,8 @@ CREATE TABLE dsolovianov.lesson_popularity_summary ON CLUSTER clickhouse_cluster ) ORDER BY (course_id, lesson_id); +DROP TABLE IF EXISTS dsolovianov.lesson_popularity_summary_mv ON CLUSTER clickhouse_cluster SYNC; + CREATE MATERIALIZED VIEW dsolovianov.lesson_popularity_summary_mv ON CLUSTER clickhouse_cluster TO dsolovianov.lesson_popularity_summary AS @@ -58,7 +60,7 @@ CREATE TABLE dsolovianov.inactive_users_summary ON CLUSTER clickhouse_cluster ( user_id UInt32, name String, email String, - age UInt8, + age UInt32, registered_courses_count UInt32, registration_date Date ) ENGINE = ReplicatedMergeTree( @@ -67,6 +69,8 @@ CREATE TABLE dsolovianov.inactive_users_summary ON CLUSTER clickhouse_cluster ( ) ORDER BY user_id; +DROP TABLE IF EXISTS dsolovianov.inactive_users_summary_mv ON CLUSTER clickhouse_cluster SYNC; + CREATE MATERIALIZED VIEW dsolovianov.inactive_users_summary_mv ON CLUSTER clickhouse_cluster TO dsolovianov.inactive_users_summary AS @@ -184,3 +188,6 @@ FROM dsolovianov.core_enrollments e JOIN dsolovianov.core_dim_user u ON e.user_id = u.user_id JOIN dsolovianov.core_dim_course c ON e.course_id = c.course_id GROUP BY e.user_id, u.name, e.course_id, c.title; + +SELECT * FROM dsolovianov.course_completion_rate ORDER BY user_id; + diff --git a/dsolovianov/clickhouse/Pet-Project/Этап 3. Анализ и запросы.sql b/dsolovianov/clickhouse/Pet-Project/Этап 3. Анализ и запросы.sql index 6550e5b..875ee9a 100644 --- a/dsolovianov/clickhouse/Pet-Project/Этап 3. Анализ и запросы.sql +++ b/dsolovianov/clickhouse/Pet-Project/Этап 3. Анализ и запросы.sql @@ -1,21 +1,25 @@ --- Этап 3. Анализ и запросы - Напиши SQL-запросы к витринам -- Напиши свои вариации для практики-- +-- Этап 3. Анализ и запросы - Напиши SQL-запросы к витринам +-- Напиши свои вариации для практики-- + + -- Топ-5 самых просматриваемых уроков SELECT lesson_title, course_title, total_views -FROM lesson_popularity_summary +FROM dsolovianov.lesson_popularity_summary ORDER BY total_views DESC LIMIT 5; + -- Неактивные пользователи, записавшиеся на курсы SELECT name, email, registered_courses_count -FROM inactive_users_summary +FROM dsolovianov.inactive_users_summary WHERE registered_courses_count > 0 ORDER BY registration_date DESC; @@ -24,7 +28,7 @@ ORDER BY registration_date DESC; SELECT course_title, AVG(completion_rate) AS avg_completion -FROM course_completion_rate +FROM dsolovianov.course_completion_rate GROUP BY course_title ORDER BY avg_completion DESC LIMIT 5; From 4828bd4afbb78b994fb8704d40eb943cdd970622 Mon Sep 17 00:00:00 2001 From: dmitry solovianov Date: Mon, 18 May 2026 19:57:59 +0400 Subject: [PATCH 42/48] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20dsolovianov/clickhouse/Pet-Project/test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dsolovianov/clickhouse/Pet-Project/test | 0 .../Этап 4. Тестирование и валидация.sql | 13 ------------- 2 files changed, 13 deletions(-) create mode 100644 dsolovianov/clickhouse/Pet-Project/test delete mode 100644 dsolovianov/clickhouse/Pet-Project/Этап 4. Тестирование и валидация.sql diff --git a/dsolovianov/clickhouse/Pet-Project/test b/dsolovianov/clickhouse/Pet-Project/test new file mode 100644 index 0000000..e69de29 diff --git a/dsolovianov/clickhouse/Pet-Project/Этап 4. Тестирование и валидация.sql b/dsolovianov/clickhouse/Pet-Project/Этап 4. Тестирование и валидация.sql deleted file mode 100644 index f053160..0000000 --- a/dsolovianov/clickhouse/Pet-Project/Этап 4. Тестирование и валидация.sql +++ /dev/null @@ -1,13 +0,0 @@ --- Этап 4. Тестирование и валидация -- - -/* -### **Задание 6: Сравни данные с Greenplum** - -1. Выбери 2–3 значения из таблиц `_summary_source` в Greenplum -2. Сравни с ClickHouse-результатами: - - Совпадает ли `SUM`, `AVG`, `MIN`, `MAX` - - Проверяй `NULL`, `0`, округления -3. Напиши мини-отчёт: **"где совпадает, где нет, почему"** -*/ - --- Ничего не понятно по этому этапу. У меня в GP нет таблиц "_summary_source" From e8cd8858fc5a124d3b50e2a2223f67863b14d767 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 18 May 2026 19:58:38 +0400 Subject: [PATCH 43/48] skip --- .../Этап 4. Тестирование и валидация.sql | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 dsolovianov/clickhouse/Pet-Project/Этап 4. Тестирование и валидация.sql diff --git a/dsolovianov/clickhouse/Pet-Project/Этап 4. Тестирование и валидация.sql b/dsolovianov/clickhouse/Pet-Project/Этап 4. Тестирование и валидация.sql deleted file mode 100644 index f053160..0000000 --- a/dsolovianov/clickhouse/Pet-Project/Этап 4. Тестирование и валидация.sql +++ /dev/null @@ -1,13 +0,0 @@ --- Этап 4. Тестирование и валидация -- - -/* -### **Задание 6: Сравни данные с Greenplum** - -1. Выбери 2–3 значения из таблиц `_summary_source` в Greenplum -2. Сравни с ClickHouse-результатами: - - Совпадает ли `SUM`, `AVG`, `MIN`, `MAX` - - Проверяй `NULL`, `0`, округления -3. Напиши мини-отчёт: **"где совпадает, где нет, почему"** -*/ - --- Ничего не понятно по этому этапу. У меня в GP нет таблиц "_summary_source" From 9a2834586e5982a7bfea0217c6fb93edd0ce3349 Mon Sep 17 00:00:00 2001 From: "valera.beretar" Date: Thu, 21 May 2026 00:56:45 +0300 Subject: [PATCH 44/48] Add homework for JOIN --- vberetar/postgresql/sql_join.sql | 144 +++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 vberetar/postgresql/sql_join.sql diff --git a/vberetar/postgresql/sql_join.sql b/vberetar/postgresql/sql_join.sql new file mode 100644 index 0000000..e2b7c55 --- /dev/null +++ b/vberetar/postgresql/sql_join.sql @@ -0,0 +1,144 @@ +-- Задание 1 +SELECT o.id AS order_id, + o.order_date, + o.status, + u.name AS user_name, + u.country +FROM orders o +JOIN users u ON o.user_id = u.id; + +-- Ответ на вопросы +-- 1. Логичнее начать c orders, так как нам в первую очередь нужны все заказы, +-- а потом только пользователи которые их сделали. + +-- 2. Я думаю уместнее сделать LEFT. +-- Я пробовал сделать с INNER и LEFT и у меня не пропали строки. +-- Получается это из за того что у каждого заказа есть пользователь, не дуаю что должен создастся заказ без пользователя. + + +-- Задание 2 +SELECT o.id AS order_id, + p.name AS product_name, + oi.quantity, + oi.price_at_purchase +FROM orders o +JOIN order_items oi ON oi.order_id = o.id +JOIN products p ON p.id = oi.product_id +WHERE o.id = 101; + +-- Ответ на вопрос +-- Выдаст дублированный состав заказа с id 101, +-- получается он будет обращаться к каждаму заказу, но отображать продукты заказа с id 101 + + +-- Задание 3 +SELECT o.id AS order_id, + u.name AS name, + p.name AS product_name, + oi.quantity, + oi.price_at_purchase +FROM orders o +JOIN users u ON u.id = o.user_id +JOIN order_items oi ON oi.order_id = o.id +JOIN products p ON p.id = oi.product_id; + +-- Ответ на вопрос +-- 1. Появляется дубликат заказов потому что у 3 заказа есть несколько товаров, join превращает(размножает) их в несколько строк. +-- 2. Отличается тем что мы выводим все заказы с товарами а не один заказ. + + +-- Задание 4 +SELECT u.name AS user_name, + o.id AS order_id, + o.status +FROM users u +LEFT JOIN orders o ON o.user_id = u.id; + +-- Ответ на вопрос +-- INNER JOIN не выдаст пользователей без заказа. Только тех у кого есть пара с orders. + + +-- Задание 5 +SELECT u.id AS user_id, + u.name AS user_name +FROM users u +LEFT JOIN orders o ON o.user_id = u.id +WHERE o.id IS NULL; + +-- Ответ на вопрос +-- 1. Проверять IS NULL нужно по полю orders.id +-- 2. Мы должны в запросе получить всех пользователей, а потом в фильтре "узнать" есть ли у них заказы. + + +-- Задание 6 +SELECT o.id AS order_id, + u.name AS user_name, + p.name AS product_name, + oi.quantity +FROM orders o +JOIN users u ON u.id = o.user_id +JOIN order_items oi ON oi.order_id = o.id +JOIN products p ON p.id = oi.product_id +WHERE p.name ILIKE '%kindle%'; + +-- Ответ на вопрос +-- В заказе 2 есть только один товар с названием Kindle. + + +-- Задание 7 +SELECT p.name AS product_name, + oi.order_id, + oi.quantity +FROM products p +LEFT JOIN order_items oi ON oi.product_id = p.id; + +-- Ответ на вопрос +-- 1. order_id будет NULL +-- 2. Если использовать INNER JOIN то он не покажет товар который не заказывали. + + +-- Задание 8 +SELECT o.id AS order_id, + u.name AS user_name, + p.name AS product_name, + oi.quantity, + oi.price_at_purchase +FROM products p +JOIN order_items oi ON oi.product_id = p.id +JOIN orders o ON o.id = oi.order_id +JOIN users u ON u.id = o.user_id +WHERE o.status = 'paid'; + +-- Ответ на вопрос +-- У меня получился тот же результат если написать вот так - JOIN orders o ON o.id = oi.order_id and o.status = 'paid' + + +-- Задание 9 +SELECT o.id AS order_id, + o.order_date, + p.name AS product_name, + oi.quantity, + oi.price_at_purchase +FROM products p +JOIN order_items oi ON oi.product_id = p.id +JOIN orders o ON o.id = oi.order_id +JOIN users u ON u.id = o.user_id +WHERE u.name = 'Alice'; + +-- Ответ на вопрос +-- Если у пользователя нет ни одного заказа, то этот запрос вернет пустую строку. +-- Не вернет потому что нечего отобразить таблице, если нет заказов то и нет купленных товаров. +-- Но если прописать RIGHT JOIN users u ON u.id = o.user_id то отобразит все строки NULL. + + +-- Задание 10 +SELECT o.id AS order_id, + o.user_id, + o.status +FROM orders o +LEFT JOIN order_items oi ON oi.order_id = o.id +WHERE oi.order_id IS NULL; + +-- Ответ на вопрос +-- Такой запрос выдаст пустые строки. +-- INNER JOIN должен выдать строки только если есть "пара". From 82d999c6f176ae9e6a5a8ebbb633eb7ff4ddc3af Mon Sep 17 00:00:00 2001 From: "valera.beretar" Date: Fri, 22 May 2026 01:09:28 +0300 Subject: [PATCH 45/48] Add homework on SQL UNION --- vberetar/postgresql/sql_union.sql | 49 +++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 vberetar/postgresql/sql_union.sql diff --git a/vberetar/postgresql/sql_union.sql b/vberetar/postgresql/sql_union.sql new file mode 100644 index 0000000..b71e744 --- /dev/null +++ b/vberetar/postgresql/sql_union.sql @@ -0,0 +1,49 @@ +-- Задание 1 +SELECT id, name, 'active' AS user_status +FROM users +WHERE is_active = TRUE +UNION ALL +SELECT id, name, 'inactive' AS user_status +FROM users +WHERE is_active = FALSE +ORDER BY name; + +-- Ответ на вопрос +-- 1. Количество строк не изменилось +-- 2. Предположу, что подача информации в таком виде более информативней(понятней). + + +-- Задание 2 +SELECT id AS order_id, user_id, order_date, 'old' AS period +FROM orders +WHERE order_date < '2024-01-01' +UNION ALL +SELECT id AS order_id, user_id, order_date, 'new' AS period +FROM orders +WHERE order_date >= '2024-01-01' +ORDER BY order_date, order_id; + +-- Ответ на вопрос +-- 1. В dbeaver в самой левой колонке отображается номерация строк, а снизу общее количество строк который выдал запрос. +-- На последней строке с old можно увидеть число в самой левой колонке, это и есть количество строк c old. Далее отнимаем общее кол-во строк от old и получаем кол-во new. +-- 2. Тяжело ответить на такой вопрос, не знаю. Если у меня были бы сомнения, я бы у новичка спросил. + + +-- Задание 3 +SELECT DISTINCT p.id AS product_id, + p.name AS product_name, + 'ordered' AS product_status +FROM products p +JOIN order_items oi ON oi.product_id = p.id +UNION ALL +SELECT DISTINCT p.id AS product_id, + p.name AS product_name, + 'never_ordered' AS product_status +FROM products p +LEFT JOIN order_items oi ON oi.product_id = p.id +WHERE oi.product_id IS NULL +ORDER BY product_name; + +-- Ответ на вопрос +-- 1. Нам нужно чтобы товар(products) ни разу не заказывали(order_items), получается что мы проверяем есть ли ссылка в каком нибудь заказе на продукт. +-- 2. Дает сигнал бизнесу что товар не хотят покупать, возможно на него нужно сделать скидку или прорекламировать товар у блогера какого нибудь. From f045be8a396b58696d4f51ab5aa5eb436eb2ed8f Mon Sep 17 00:00:00 2001 From: mnoskov Date: Thu, 28 May 2026 18:00:56 +0300 Subject: [PATCH 46/48] =?UTF-8?q?=D1=83=D0=B1=D1=80=D0=B0=D0=BB=20:=20?= =?UTF-8?q?=D0=B8=D0=B7=20=D0=BF=D0=B0=D0=BF=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Этап 1. Загрузка тестовых данных/csv files/dim_course_202605201139.csv | 0 .../Этап 1. Загрузка тестовых данных/csv files/dim_date_202605191312.csv | 0 .../Этап 1. Загрузка тестовых данных/csv files/dim_lesson_202605191312.csv | 0 .../Этап 1. Загрузка тестовых данных/csv files/dim_user_202605201142.csv | 0 .../Этап 1. Загрузка тестовых данных/csv files/enrollments_202605201134.csv | 0 .../Этап 1. Загрузка тестовых данных/csv files/fact_lesson_views_202605191356.csv | 0 .../Этап 1. Загрузка тестовых данных/task_1_upload_csv_files.sql | 0 .../Этап 2. Создание витринных таблиц/task_2_lesson_popularity_summary.sql | 0 .../Этап 2. Создание витринных таблиц/task_3_inactive_users_summary.sql | 0 .../Этап 2. Создание витринных таблиц/task_4_course_completion_rate.sql | 0 .../Этап 3. Анализ и запросы/Task_5_SQL_queries_for_dm.sql | 0 .../Этап 4. Тестирование и валидация/task_6_compare_data_with_Greenplum.txt | 0 .../Step_1_project_Initialization.sql | 0 .../Step_2_Loading Data}/courses_202604212117.csv | 0 .../Step_2_Loading Data}/enrollments_202604212130.csv | 0 .../Step_2_Loading Data}/lesson_views_202604212133.csv | 0 .../Step_2_Loading Data}/lessons_202604212131.csv | 0 .../Step_2_Loading Data}/users_202604212132.csv | 0 .../{Пет проект: DWH => Пет проект DWH}/Step_3_core_layer.sql | 0 .../Step_4_preparing_display_cases_at_greenplum.sql | 0 .../{Пет проект: DWH => Пет проект DWH}/Step_5_verification.sql | 0 .../1. Создание таблиц и связей/DDL_create_tables_for_pet_project.sql | 0 .../1. Создание таблиц и связей/DML_insert_in_tables_for_pet_project.sql | 0 .../2. Создание отчетности (витрин)/DQL_materialized_view_cohort_analysis_of_users.sql | 0 .../2. Создание отчетности (витрин)/DQL_materialized_view_conversion_funnel.sql | 0 .../2. Создание отчетности (витрин)/DQL_materialized_view_courses_effectivity.sql | 0 .../2. Создание отчетности (витрин)/DQL_materialized_view_courses_popularity.sql | 0 .../2. Создание отчетности (витрин)/DQL_materialized_view_reporting_on_interactions.sql | 0 .../2. Создание отчетности (витрин)/DQL_materialized_view_user_activity_summary.sql | 0 .../3. Доп. задания/DQL_additional_tasks.sql | 0 30 files changed, 0 insertions(+), 0 deletions(-) rename mnoskov/clickhouse/{Пет-проект: Витринный слой => Пет-проект Витринный слой}/Этап 1. Загрузка тестовых данных/csv files/dim_course_202605201139.csv (100%) rename mnoskov/clickhouse/{Пет-проект: Витринный слой => Пет-проект Витринный слой}/Этап 1. Загрузка тестовых данных/csv files/dim_date_202605191312.csv (100%) rename mnoskov/clickhouse/{Пет-проект: Витринный слой => Пет-проект Витринный слой}/Этап 1. Загрузка тестовых данных/csv files/dim_lesson_202605191312.csv (100%) rename mnoskov/clickhouse/{Пет-проект: Витринный слой => Пет-проект Витринный слой}/Этап 1. Загрузка тестовых данных/csv files/dim_user_202605201142.csv (100%) rename mnoskov/clickhouse/{Пет-проект: Витринный слой => Пет-проект Витринный слой}/Этап 1. Загрузка тестовых данных/csv files/enrollments_202605201134.csv (100%) rename mnoskov/clickhouse/{Пет-проект: Витринный слой => Пет-проект Витринный слой}/Этап 1. Загрузка тестовых данных/csv files/fact_lesson_views_202605191356.csv (100%) rename mnoskov/clickhouse/{Пет-проект: Витринный слой => Пет-проект Витринный слой}/Этап 1. Загрузка тестовых данных/task_1_upload_csv_files.sql (100%) rename mnoskov/clickhouse/{Пет-проект: Витринный слой => Пет-проект Витринный слой}/Этап 2. Создание витринных таблиц/task_2_lesson_popularity_summary.sql (100%) rename mnoskov/clickhouse/{Пет-проект: Витринный слой => Пет-проект Витринный слой}/Этап 2. Создание витринных таблиц/task_3_inactive_users_summary.sql (100%) rename mnoskov/clickhouse/{Пет-проект: Витринный слой => Пет-проект Витринный слой}/Этап 2. Создание витринных таблиц/task_4_course_completion_rate.sql (100%) rename mnoskov/clickhouse/{Пет-проект: Витринный слой => Пет-проект Витринный слой}/Этап 3. Анализ и запросы/Task_5_SQL_queries_for_dm.sql (100%) rename mnoskov/clickhouse/{Пет-проект: Витринный слой => Пет-проект Витринный слой}/Этап 4. Тестирование и валидация/task_6_compare_data_with_Greenplum.txt (100%) rename mnoskov/greenplum/{Пет проект: DWH => Пет проект DWH}/Step_1_project_Initialization.sql (100%) rename mnoskov/greenplum/{Пет проект: DWH/Step 2: Loading Data => Пет проект DWH/Step_2_Loading Data}/courses_202604212117.csv (100%) rename mnoskov/greenplum/{Пет проект: DWH/Step 2: Loading Data => Пет проект DWH/Step_2_Loading Data}/enrollments_202604212130.csv (100%) rename mnoskov/greenplum/{Пет проект: DWH/Step 2: Loading Data => Пет проект DWH/Step_2_Loading Data}/lesson_views_202604212133.csv (100%) rename mnoskov/greenplum/{Пет проект: DWH/Step 2: Loading Data => Пет проект DWH/Step_2_Loading Data}/lessons_202604212131.csv (100%) rename mnoskov/greenplum/{Пет проект: DWH/Step 2: Loading Data => Пет проект DWH/Step_2_Loading Data}/users_202604212132.csv (100%) rename mnoskov/greenplum/{Пет проект: DWH => Пет проект DWH}/Step_3_core_layer.sql (100%) rename mnoskov/greenplum/{Пет проект: DWH => Пет проект DWH}/Step_4_preparing_display_cases_at_greenplum.sql (100%) rename mnoskov/greenplum/{Пет проект: DWH => Пет проект DWH}/Step_5_verification.sql (100%) rename mnoskov/postgresql/{Пет-проект: Онлайн-курсы => Пет-проект Онлайн-курсы}/1. Создание таблиц и связей/DDL_create_tables_for_pet_project.sql (100%) rename mnoskov/postgresql/{Пет-проект: Онлайн-курсы => Пет-проект Онлайн-курсы}/1. Создание таблиц и связей/DML_insert_in_tables_for_pet_project.sql (100%) rename mnoskov/postgresql/{Пет-проект: Онлайн-курсы => Пет-проект Онлайн-курсы}/2. Создание отчетности (витрин)/DQL_materialized_view_cohort_analysis_of_users.sql (100%) rename mnoskov/postgresql/{Пет-проект: Онлайн-курсы => Пет-проект Онлайн-курсы}/2. Создание отчетности (витрин)/DQL_materialized_view_conversion_funnel.sql (100%) rename mnoskov/postgresql/{Пет-проект: Онлайн-курсы => Пет-проект Онлайн-курсы}/2. Создание отчетности (витрин)/DQL_materialized_view_courses_effectivity.sql (100%) rename mnoskov/postgresql/{Пет-проект: Онлайн-курсы => Пет-проект Онлайн-курсы}/2. Создание отчетности (витрин)/DQL_materialized_view_courses_popularity.sql (100%) rename mnoskov/postgresql/{Пет-проект: Онлайн-курсы => Пет-проект Онлайн-курсы}/2. Создание отчетности (витрин)/DQL_materialized_view_reporting_on_interactions.sql (100%) rename mnoskov/postgresql/{Пет-проект: Онлайн-курсы => Пет-проект Онлайн-курсы}/2. Создание отчетности (витрин)/DQL_materialized_view_user_activity_summary.sql (100%) rename mnoskov/postgresql/{Пет-проект: Онлайн-курсы => Пет-проект Онлайн-курсы}/3. Доп. задания/DQL_additional_tasks.sql (100%) diff --git a/mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_course_202605201139.csv b/mnoskov/clickhouse/Пет-проект Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_course_202605201139.csv similarity index 100% rename from mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_course_202605201139.csv rename to mnoskov/clickhouse/Пет-проект Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_course_202605201139.csv diff --git a/mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_date_202605191312.csv b/mnoskov/clickhouse/Пет-проект Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_date_202605191312.csv similarity index 100% rename from mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_date_202605191312.csv rename to mnoskov/clickhouse/Пет-проект Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_date_202605191312.csv diff --git a/mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_lesson_202605191312.csv b/mnoskov/clickhouse/Пет-проект Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_lesson_202605191312.csv similarity index 100% rename from mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_lesson_202605191312.csv rename to mnoskov/clickhouse/Пет-проект Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_lesson_202605191312.csv diff --git a/mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_user_202605201142.csv b/mnoskov/clickhouse/Пет-проект Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_user_202605201142.csv similarity index 100% rename from mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_user_202605201142.csv rename to mnoskov/clickhouse/Пет-проект Витринный слой/Этап 1. Загрузка тестовых данных/csv files/dim_user_202605201142.csv diff --git a/mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 1. Загрузка тестовых данных/csv files/enrollments_202605201134.csv b/mnoskov/clickhouse/Пет-проект Витринный слой/Этап 1. Загрузка тестовых данных/csv files/enrollments_202605201134.csv similarity index 100% rename from mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 1. Загрузка тестовых данных/csv files/enrollments_202605201134.csv rename to mnoskov/clickhouse/Пет-проект Витринный слой/Этап 1. Загрузка тестовых данных/csv files/enrollments_202605201134.csv diff --git a/mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 1. Загрузка тестовых данных/csv files/fact_lesson_views_202605191356.csv b/mnoskov/clickhouse/Пет-проект Витринный слой/Этап 1. Загрузка тестовых данных/csv files/fact_lesson_views_202605191356.csv similarity index 100% rename from mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 1. Загрузка тестовых данных/csv files/fact_lesson_views_202605191356.csv rename to mnoskov/clickhouse/Пет-проект Витринный слой/Этап 1. Загрузка тестовых данных/csv files/fact_lesson_views_202605191356.csv diff --git a/mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 1. Загрузка тестовых данных/task_1_upload_csv_files.sql b/mnoskov/clickhouse/Пет-проект Витринный слой/Этап 1. Загрузка тестовых данных/task_1_upload_csv_files.sql similarity index 100% rename from mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 1. Загрузка тестовых данных/task_1_upload_csv_files.sql rename to mnoskov/clickhouse/Пет-проект Витринный слой/Этап 1. Загрузка тестовых данных/task_1_upload_csv_files.sql diff --git a/mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 2. Создание витринных таблиц/task_2_lesson_popularity_summary.sql b/mnoskov/clickhouse/Пет-проект Витринный слой/Этап 2. Создание витринных таблиц/task_2_lesson_popularity_summary.sql similarity index 100% rename from mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 2. Создание витринных таблиц/task_2_lesson_popularity_summary.sql rename to mnoskov/clickhouse/Пет-проект Витринный слой/Этап 2. Создание витринных таблиц/task_2_lesson_popularity_summary.sql diff --git a/mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 2. Создание витринных таблиц/task_3_inactive_users_summary.sql b/mnoskov/clickhouse/Пет-проект Витринный слой/Этап 2. Создание витринных таблиц/task_3_inactive_users_summary.sql similarity index 100% rename from mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 2. Создание витринных таблиц/task_3_inactive_users_summary.sql rename to mnoskov/clickhouse/Пет-проект Витринный слой/Этап 2. Создание витринных таблиц/task_3_inactive_users_summary.sql diff --git a/mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 2. Создание витринных таблиц/task_4_course_completion_rate.sql b/mnoskov/clickhouse/Пет-проект Витринный слой/Этап 2. Создание витринных таблиц/task_4_course_completion_rate.sql similarity index 100% rename from mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 2. Создание витринных таблиц/task_4_course_completion_rate.sql rename to mnoskov/clickhouse/Пет-проект Витринный слой/Этап 2. Создание витринных таблиц/task_4_course_completion_rate.sql diff --git a/mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 3. Анализ и запросы/Task_5_SQL_queries_for_dm.sql b/mnoskov/clickhouse/Пет-проект Витринный слой/Этап 3. Анализ и запросы/Task_5_SQL_queries_for_dm.sql similarity index 100% rename from mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 3. Анализ и запросы/Task_5_SQL_queries_for_dm.sql rename to mnoskov/clickhouse/Пет-проект Витринный слой/Этап 3. Анализ и запросы/Task_5_SQL_queries_for_dm.sql diff --git a/mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 4. Тестирование и валидация/task_6_compare_data_with_Greenplum.txt b/mnoskov/clickhouse/Пет-проект Витринный слой/Этап 4. Тестирование и валидация/task_6_compare_data_with_Greenplum.txt similarity index 100% rename from mnoskov/clickhouse/Пет-проект: Витринный слой/Этап 4. Тестирование и валидация/task_6_compare_data_with_Greenplum.txt rename to mnoskov/clickhouse/Пет-проект Витринный слой/Этап 4. Тестирование и валидация/task_6_compare_data_with_Greenplum.txt diff --git a/mnoskov/greenplum/Пет проект: DWH/Step_1_project_Initialization.sql b/mnoskov/greenplum/Пет проект DWH/Step_1_project_Initialization.sql similarity index 100% rename from mnoskov/greenplum/Пет проект: DWH/Step_1_project_Initialization.sql rename to mnoskov/greenplum/Пет проект DWH/Step_1_project_Initialization.sql diff --git a/mnoskov/greenplum/Пет проект: DWH/Step 2: Loading Data/courses_202604212117.csv b/mnoskov/greenplum/Пет проект DWH/Step_2_Loading Data/courses_202604212117.csv similarity index 100% rename from mnoskov/greenplum/Пет проект: DWH/Step 2: Loading Data/courses_202604212117.csv rename to mnoskov/greenplum/Пет проект DWH/Step_2_Loading Data/courses_202604212117.csv diff --git a/mnoskov/greenplum/Пет проект: DWH/Step 2: Loading Data/enrollments_202604212130.csv b/mnoskov/greenplum/Пет проект DWH/Step_2_Loading Data/enrollments_202604212130.csv similarity index 100% rename from mnoskov/greenplum/Пет проект: DWH/Step 2: Loading Data/enrollments_202604212130.csv rename to mnoskov/greenplum/Пет проект DWH/Step_2_Loading Data/enrollments_202604212130.csv diff --git a/mnoskov/greenplum/Пет проект: DWH/Step 2: Loading Data/lesson_views_202604212133.csv b/mnoskov/greenplum/Пет проект DWH/Step_2_Loading Data/lesson_views_202604212133.csv similarity index 100% rename from mnoskov/greenplum/Пет проект: DWH/Step 2: Loading Data/lesson_views_202604212133.csv rename to mnoskov/greenplum/Пет проект DWH/Step_2_Loading Data/lesson_views_202604212133.csv diff --git a/mnoskov/greenplum/Пет проект: DWH/Step 2: Loading Data/lessons_202604212131.csv b/mnoskov/greenplum/Пет проект DWH/Step_2_Loading Data/lessons_202604212131.csv similarity index 100% rename from mnoskov/greenplum/Пет проект: DWH/Step 2: Loading Data/lessons_202604212131.csv rename to mnoskov/greenplum/Пет проект DWH/Step_2_Loading Data/lessons_202604212131.csv diff --git a/mnoskov/greenplum/Пет проект: DWH/Step 2: Loading Data/users_202604212132.csv b/mnoskov/greenplum/Пет проект DWH/Step_2_Loading Data/users_202604212132.csv similarity index 100% rename from mnoskov/greenplum/Пет проект: DWH/Step 2: Loading Data/users_202604212132.csv rename to mnoskov/greenplum/Пет проект DWH/Step_2_Loading Data/users_202604212132.csv diff --git a/mnoskov/greenplum/Пет проект: DWH/Step_3_core_layer.sql b/mnoskov/greenplum/Пет проект DWH/Step_3_core_layer.sql similarity index 100% rename from mnoskov/greenplum/Пет проект: DWH/Step_3_core_layer.sql rename to mnoskov/greenplum/Пет проект DWH/Step_3_core_layer.sql diff --git a/mnoskov/greenplum/Пет проект: DWH/Step_4_preparing_display_cases_at_greenplum.sql b/mnoskov/greenplum/Пет проект DWH/Step_4_preparing_display_cases_at_greenplum.sql similarity index 100% rename from mnoskov/greenplum/Пет проект: DWH/Step_4_preparing_display_cases_at_greenplum.sql rename to mnoskov/greenplum/Пет проект DWH/Step_4_preparing_display_cases_at_greenplum.sql diff --git a/mnoskov/greenplum/Пет проект: DWH/Step_5_verification.sql b/mnoskov/greenplum/Пет проект DWH/Step_5_verification.sql similarity index 100% rename from mnoskov/greenplum/Пет проект: DWH/Step_5_verification.sql rename to mnoskov/greenplum/Пет проект DWH/Step_5_verification.sql diff --git a/mnoskov/postgresql/Пет-проект: Онлайн-курсы/1. Создание таблиц и связей/DDL_create_tables_for_pet_project.sql b/mnoskov/postgresql/Пет-проект Онлайн-курсы/1. Создание таблиц и связей/DDL_create_tables_for_pet_project.sql similarity index 100% rename from mnoskov/postgresql/Пет-проект: Онлайн-курсы/1. Создание таблиц и связей/DDL_create_tables_for_pet_project.sql rename to mnoskov/postgresql/Пет-проект Онлайн-курсы/1. Создание таблиц и связей/DDL_create_tables_for_pet_project.sql diff --git a/mnoskov/postgresql/Пет-проект: Онлайн-курсы/1. Создание таблиц и связей/DML_insert_in_tables_for_pet_project.sql b/mnoskov/postgresql/Пет-проект Онлайн-курсы/1. Создание таблиц и связей/DML_insert_in_tables_for_pet_project.sql similarity index 100% rename from mnoskov/postgresql/Пет-проект: Онлайн-курсы/1. Создание таблиц и связей/DML_insert_in_tables_for_pet_project.sql rename to mnoskov/postgresql/Пет-проект Онлайн-курсы/1. Создание таблиц и связей/DML_insert_in_tables_for_pet_project.sql diff --git a/mnoskov/postgresql/Пет-проект: Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_cohort_analysis_of_users.sql b/mnoskov/postgresql/Пет-проект Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_cohort_analysis_of_users.sql similarity index 100% rename from mnoskov/postgresql/Пет-проект: Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_cohort_analysis_of_users.sql rename to mnoskov/postgresql/Пет-проект Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_cohort_analysis_of_users.sql diff --git a/mnoskov/postgresql/Пет-проект: Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_conversion_funnel.sql b/mnoskov/postgresql/Пет-проект Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_conversion_funnel.sql similarity index 100% rename from mnoskov/postgresql/Пет-проект: Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_conversion_funnel.sql rename to mnoskov/postgresql/Пет-проект Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_conversion_funnel.sql diff --git a/mnoskov/postgresql/Пет-проект: Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_courses_effectivity.sql b/mnoskov/postgresql/Пет-проект Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_courses_effectivity.sql similarity index 100% rename from mnoskov/postgresql/Пет-проект: Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_courses_effectivity.sql rename to mnoskov/postgresql/Пет-проект Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_courses_effectivity.sql diff --git a/mnoskov/postgresql/Пет-проект: Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_courses_popularity.sql b/mnoskov/postgresql/Пет-проект Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_courses_popularity.sql similarity index 100% rename from mnoskov/postgresql/Пет-проект: Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_courses_popularity.sql rename to mnoskov/postgresql/Пет-проект Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_courses_popularity.sql diff --git a/mnoskov/postgresql/Пет-проект: Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_reporting_on_interactions.sql b/mnoskov/postgresql/Пет-проект Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_reporting_on_interactions.sql similarity index 100% rename from mnoskov/postgresql/Пет-проект: Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_reporting_on_interactions.sql rename to mnoskov/postgresql/Пет-проект Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_reporting_on_interactions.sql diff --git a/mnoskov/postgresql/Пет-проект: Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_user_activity_summary.sql b/mnoskov/postgresql/Пет-проект Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_user_activity_summary.sql similarity index 100% rename from mnoskov/postgresql/Пет-проект: Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_user_activity_summary.sql rename to mnoskov/postgresql/Пет-проект Онлайн-курсы/2. Создание отчетности (витрин)/DQL_materialized_view_user_activity_summary.sql diff --git a/mnoskov/postgresql/Пет-проект: Онлайн-курсы/3. Доп. задания/DQL_additional_tasks.sql b/mnoskov/postgresql/Пет-проект Онлайн-курсы/3. Доп. задания/DQL_additional_tasks.sql similarity index 100% rename from mnoskov/postgresql/Пет-проект: Онлайн-курсы/3. Доп. задания/DQL_additional_tasks.sql rename to mnoskov/postgresql/Пет-проект Онлайн-курсы/3. Доп. задания/DQL_additional_tasks.sql From dd868283ed7b8c75022021b7ab5c4daed259aa0c Mon Sep 17 00:00:00 2001 From: mnoskov Date: Thu, 28 May 2026 18:13:59 +0300 Subject: [PATCH 47/48] =?UTF-8?q?=D1=83=D0=B1=D1=80=D0=B0=D0=BB=20=D0=B4?= =?UTF-8?q?=D0=B2=D0=B0=20=D0=B4=D0=B2=D0=BE=D0=B5=D1=82=D0=BE=D1=87=D0=B8?= =?UTF-8?q?=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DQL_functions_practice.sql | 0 .../{5. Индексы: Алгоритмы => 5. Индексы Алгоритмы}/practice_indexes_algorithms.sql | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename mnoskov/postgresql/SQL с нуля/{5. Функции: даты, строки, логика => 5. Функции даты, строки, логика}/DQL_functions_practice.sql (100%) rename mnoskov/Теория БД/1. Ускорение и масштабирование/{5. Индексы: Алгоритмы => 5. Индексы Алгоритмы}/practice_indexes_algorithms.sql (100%) diff --git a/mnoskov/postgresql/SQL с нуля/5. Функции: даты, строки, логика/DQL_functions_practice.sql b/mnoskov/postgresql/SQL с нуля/5. Функции даты, строки, логика/DQL_functions_practice.sql similarity index 100% rename from mnoskov/postgresql/SQL с нуля/5. Функции: даты, строки, логика/DQL_functions_practice.sql rename to mnoskov/postgresql/SQL с нуля/5. Функции даты, строки, логика/DQL_functions_practice.sql diff --git a/mnoskov/Теория БД/1. Ускорение и масштабирование/5. Индексы: Алгоритмы/practice_indexes_algorithms.sql b/mnoskov/Теория БД/1. Ускорение и масштабирование/5. Индексы Алгоритмы/practice_indexes_algorithms.sql similarity index 100% rename from mnoskov/Теория БД/1. Ускорение и масштабирование/5. Индексы: Алгоритмы/practice_indexes_algorithms.sql rename to mnoskov/Теория БД/1. Ускорение и масштабирование/5. Индексы Алгоритмы/practice_indexes_algorithms.sql From a547afe5dbaa0b52f7dd4bf3c736e1cc18c6738f Mon Sep 17 00:00:00 2001 From: mnoskov Date: Thu, 28 May 2026 18:17:25 +0300 Subject: [PATCH 48/48] =?UTF-8?q?=D1=83=D0=B1=D1=80=D0=B0=D0=BB=20:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../practice_arrays_maps_and_nested_structures.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename mnoskov/clickhouse/Практика clickhouse/2. Запросы/{3. Массивы, Map и вложенные структуры* => 3. Массивы, Map и вложенные структуры}/practice_arrays_maps_and_nested_structures.sql (100%) diff --git a/mnoskov/clickhouse/Практика clickhouse/2. Запросы/3. Массивы, Map и вложенные структуры*/practice_arrays_maps_and_nested_structures.sql b/mnoskov/clickhouse/Практика clickhouse/2. Запросы/3. Массивы, Map и вложенные структуры/practice_arrays_maps_and_nested_structures.sql similarity index 100% rename from mnoskov/clickhouse/Практика clickhouse/2. Запросы/3. Массивы, Map и вложенные структуры*/practice_arrays_maps_and_nested_structures.sql rename to mnoskov/clickhouse/Практика clickhouse/2. Запросы/3. Массивы, Map и вложенные структуры/practice_arrays_maps_and_nested_structures.sql