From 69e227b59fab5fc17491c61d6aeaa365cad156d1 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 15 Jan 2026 06:03:41 +0300 Subject: [PATCH 01/28] SQL homework done 1st lesson --- aharlamcev/postgresql/sqlhomework.sql | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 aharlamcev/postgresql/sqlhomework.sql diff --git a/aharlamcev/postgresql/sqlhomework.sql b/aharlamcev/postgresql/sqlhomework.sql new file mode 100644 index 0000000..4fb1078 --- /dev/null +++ b/aharlamcev/postgresql/sqlhomework.sql @@ -0,0 +1,23 @@ +create table products_extended ( +id INT primary key, +name VARCHAR(100) not null, +category VARCHAR(50), +price DECIMAL(10, 2), +in_stock BOOLEAN default true, +email_support VARCHAR(50) +); + +insert into products_extended (id, name, category, price, in_stock, email_support) +values (1, 'Mi Band 7', 'smartwatch', 49, true, 'miband@xiaomi.com'); + +insert into products_extended (id, name, category, price, in_stock, email_support) +values (2, 'Surface Pro', 'tablet', 1299, true, 'surface@microsoft.com'); + +select * from products_extended -- проверил как выглядит таблица + +alter table products_extended +add column rating DECIMAL(5, 2); + +truncate table products_extended; + +drop table products_extended From f050458471e3959dc4bf7ad2740a56f95104dae3 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 17 Jan 2026 10:02:47 +0300 Subject: [PATCH 02/28] Created tables users, products, orders, order_items. --- aharlamcev/postgresql/homeworkDDL.sql | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 aharlamcev/postgresql/homeworkDDL.sql diff --git a/aharlamcev/postgresql/homeworkDDL.sql b/aharlamcev/postgresql/homeworkDDL.sql new file mode 100644 index 0000000..7bc5255 --- /dev/null +++ b/aharlamcev/postgresql/homeworkDDL.sql @@ -0,0 +1,32 @@ +create table users ( +id int primary key, +name VARCHAR(100) not null, +email VARCHAR(100), +country VARCHAR(50), +crated_at date not null +) ; + +create table products ( +id int primary key, +name VARCHAR(100) not null, +category VARCHAR(50), +price DECIMAL(10, 2), +in_stock BOOLEAN default true +) ; + +create table orders ( +id int primary key, +user_id int, +order_date DATE not null, +status VARCHAR(20), +foreign key (user_id) references users(id) +) ; + +create table order_items ( +order_id int, +product_id int, +quantity int not null, +price_at_purchase DECIMAL(10, 2) not null, +foreign key (order_id) references orders(id), +foreign key (product_id) references products(id) +) ; \ No newline at end of file From 65b40c69a0bb5d64f32233aa021a0728ffc19157 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 17 Jan 2026 14:45:48 +0300 Subject: [PATCH 03/28] renamed column created_at --- aharlamcev/postgresql/homeworkDDL.sql | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/aharlamcev/postgresql/homeworkDDL.sql b/aharlamcev/postgresql/homeworkDDL.sql index 7bc5255..5e43015 100644 --- a/aharlamcev/postgresql/homeworkDDL.sql +++ b/aharlamcev/postgresql/homeworkDDL.sql @@ -29,4 +29,7 @@ quantity int not null, price_at_purchase DECIMAL(10, 2) not null, foreign key (order_id) references orders(id), foreign key (product_id) references products(id) -) ; \ No newline at end of file +) ; + +alter table users +rename column crated_at to created_at; \ No newline at end of file From 631cf7fe4fbbd7256d2ed75857c1e3fec778c5f6 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 18 Jan 2026 13:27:47 +0300 Subject: [PATCH 04/28] DML inserted rows --- aharlamcev/postgresql/DMLhomework | 52 +++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 aharlamcev/postgresql/DMLhomework diff --git a/aharlamcev/postgresql/DMLhomework b/aharlamcev/postgresql/DMLhomework new file mode 100644 index 0000000..b50c436 --- /dev/null +++ b/aharlamcev/postgresql/DMLhomework @@ -0,0 +1,52 @@ +select * from users + +insert into users (id, name, email, country, created_at) +values (1, 'Alice', null, 'KZ', '2026-01-17'); + +insert into users (id, name, email, country, created_at) +values (2, 'Bob', null, 'USA', '2026-01-17'); + +insert into users (id, name, email, country, created_at) +values (3, 'Charlie', null, 'RU', '2026-01-17'); + +select * from products + +insert into products (id, name, category, price, in_stock) +values (1, 'Mi Band 7', 'smartwatch', 49, true) + +insert into products (id, name, category, price, in_stock) +values (2, 'Surface Pro', 'tablet', 1299, true) + +insert into products (id, name, category, price, in_stock) +values (3, 'Iphone 15', 'smartphone', 999, true) + +insert into products (id, name, category, price, in_stock) +values (4, 'Logitech MX Master', 'mouse', 120, true) + +insert into orders (id, user_id, order_date, status) +values (1, 1, '2026-01-17', 'in delivery'); + +insert into orders (id, user_id, order_date, status) +values (2, 1, '2026-01-17', 'shipped'); + +insert into orders (id, user_id, order_date, status) +values (3, 2, '2026-01-17', 'preparing'); + +select * from order_items + +insert into order_items (order_id, product_id, quantity, price_at_purchase) +values (1,1, 2, 49) + +insert into order_items (order_id, product_id, quantity, price_at_purchase) +values (1, 2, 1, 1299) + +insert into order_items (order_id, product_id, quantity, price_at_purchase) +values (2, 3, 1, 999) + +insert into order_items (order_id, product_id, quantity, price_at_purchase) +values (3, 4, 2, 120) + +insert into order_items (order_id, product_id, quantity, price_at_purchase) +values (3, 1, 2, 49) + +-- Сейчас уже понял, что можно после insert - values добавлять сразу в скобках несколько штук, но изначально делал так. \ No newline at end of file From 93c3846ead451c5bb60e26b917f46f891cdcd6c1 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 18 Jan 2026 13:57:09 +0300 Subject: [PATCH 05/28] Base SQL homework --- aharlamcev/postgresql/BaseSQLhomework.sql | 28 +++++++++++++++++++ .../{DMLhomework => DMLhomework.sql} | 0 2 files changed, 28 insertions(+) create mode 100644 aharlamcev/postgresql/BaseSQLhomework.sql rename aharlamcev/postgresql/{DMLhomework => DMLhomework.sql} (100%) diff --git a/aharlamcev/postgresql/BaseSQLhomework.sql b/aharlamcev/postgresql/BaseSQLhomework.sql new file mode 100644 index 0000000..92666f2 --- /dev/null +++ b/aharlamcev/postgresql/BaseSQLhomework.sql @@ -0,0 +1,28 @@ +select * from users + +select id, name, country from users +order by name; + +select id, name, country, created_at from users +where country = 'KZ' +order by created_at desc; + +select id, name from users +where email is null; + +select id, name from users +where email is not null; + +update users +set email = 'alice@mail.com' +where name = 'Alice'; -- в моей таблице ни у кого нет email, добавил чтобы посмотреть. + +select id, name, UPPER(email) as email_upper from users; + +select id, name, LOWER(email) as email_lower from users +where email is not null; + +select id, name, created_at from users +where created_at > '2024-01-11' +order by created_at desc +limit 2; diff --git a/aharlamcev/postgresql/DMLhomework b/aharlamcev/postgresql/DMLhomework.sql similarity index 100% rename from aharlamcev/postgresql/DMLhomework rename to aharlamcev/postgresql/DMLhomework.sql From e3ddb8f5b22a6bf4af9aadacfe6b105c3ada7281 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 18 Jan 2026 14:30:51 +0300 Subject: [PATCH 06/28] filtration homework --- aharlamcev/postgresql/Filtrationhomework.sql | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 aharlamcev/postgresql/Filtrationhomework.sql diff --git a/aharlamcev/postgresql/Filtrationhomework.sql b/aharlamcev/postgresql/Filtrationhomework.sql new file mode 100644 index 0000000..b8d9407 --- /dev/null +++ b/aharlamcev/postgresql/Filtrationhomework.sql @@ -0,0 +1,22 @@ +select * from products + +select name, category, price, price * 1.3 as price_with_markup, price * 1.5 as price_with_vat +from products +where in_stock is true and category != 'smartwatch' and price between 100 and 1300; + +select name, price, price * 0.85 as price_with_discount +from products +where price < 100 or price > 1000; + +select id, name, category, price from products +where category in ('tablet', 'smartphone', 'mouse') and price > 100; + +select name, category, price from products +where name not ilike '%iphone%'; + +select name, category, price from products +where name ilike '%pro%'; + +select name, category, price from products +where name ilike '%mx%' +order by price desc; \ No newline at end of file From 5d31d01875c478fb285ec8fb839367d7bb2f4f39 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 1 Feb 2026 10:04:31 +0300 Subject: [PATCH 07/28] window function Task 1 completed --- .../postgresql/WindowFunctionHomework.sql | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 aharlamcev/postgresql/WindowFunctionHomework.sql diff --git a/aharlamcev/postgresql/WindowFunctionHomework.sql b/aharlamcev/postgresql/WindowFunctionHomework.sql new file mode 100644 index 0000000..72dd993 --- /dev/null +++ b/aharlamcev/postgresql/WindowFunctionHomework.sql @@ -0,0 +1,39 @@ +create table products_extended ( +id INT primary key, +name VARCHAR(50) not null, +category VARCHAR(50) not null, +price INT, +in_stock BOOLEAN default true, +email_support VARCHAR(50) +); + +insert into products_extended (id, name, category, price, in_stock, email_support) +values (1, 'iPhone 14', 'smartphone', 799, true, 'iphone@apple.com'), +(2, 'MacBook Air', 'laptop', 1199, false, NULL), +(3, 'Galaxy S22', 'smartphone', 699, true, 'galaxy@support.com'), +(4, 'ThinkPad X1', 'laptop', 1399, true, 'thinkpad@lenovo.com'), +(5, 'iPad Pro', 'tablet', 999, false, 'ipad@apple.com'), +(6, 'Kindle Paperwhite', 'ebook_reader', 149, true, NULL), +(7, 'Mi Band 7', 'smartwatch', 49, true, 'miband@xiaomi.com'), +(8, 'Surface Pro', 'tablet', 1299, true, 'surface@microsoft.com'), +(9, 'Honor Pad X9', 'tablet', 219, true, 'honor@support.com'), +(10, 'Dell XPS 13', 'laptop', 1099, false, 'dell@support.com'); + +select * from products_extended + +with email_false as (select * from +( +select category, name, price, email_support, row_number() over (partition by category order by price desc) as rn +from products_extended where email_support is null) +), + +email_true as (select * from +( +select category, name, price, email_support, row_number() over (partition by category order by price desc) as rn +from products_extended where email_support is not null) where rn = 1 +) + +select category, name, price, email_support from email_false +union all +select category, name, price, email_support from email_true +order by category, price desc From 63f391d689884e46364143b8ec220a659efa03d1 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 1 Feb 2026 13:17:20 +0300 Subject: [PATCH 08/28] fixed --- aharlamcev/postgresql/WindowFunctionHomework.sql | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/aharlamcev/postgresql/WindowFunctionHomework.sql b/aharlamcev/postgresql/WindowFunctionHomework.sql index 72dd993..bd81ac9 100644 --- a/aharlamcev/postgresql/WindowFunctionHomework.sql +++ b/aharlamcev/postgresql/WindowFunctionHomework.sql @@ -19,12 +19,15 @@ values (1, 'iPhone 14', 'smartphone', 799, true, 'iphone@apple.com'), (9, 'Honor Pad X9', 'tablet', 219, true, 'honor@support.com'), (10, 'Dell XPS 13', 'laptop', 1099, false, 'dell@support.com'); +alter table products_extended +alter column price type DECIMAL(10, 2) + select * from products_extended with email_false as (select * from ( select category, name, price, email_support, row_number() over (partition by category order by price desc) as rn -from products_extended where email_support is null) +from products_extended where email_support is null) where rn = 1 ), email_true as (select * from From b7c7dcf012aee9db4c8db0e22d656366046b8611 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 5 Feb 2026 13:44:24 +0300 Subject: [PATCH 09/28] WindowFuncs Homework done --- .../postgresql/WindowFunctionHomework.sql | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/aharlamcev/postgresql/WindowFunctionHomework.sql b/aharlamcev/postgresql/WindowFunctionHomework.sql index bd81ac9..0e16bf1 100644 --- a/aharlamcev/postgresql/WindowFunctionHomework.sql +++ b/aharlamcev/postgresql/WindowFunctionHomework.sql @@ -22,21 +22,51 @@ values (1, 'iPhone 14', 'smartphone', 799, true, 'iphone@apple.com'), alter table products_extended alter column price type DECIMAL(10, 2) -select * from products_extended - +------------------ Задание №1 (По нему ты говорил, что нечитаемо, объясни как переделать pls <3) with email_false as (select * from ( -select category, name, price, email_support, row_number() over (partition by category order by price desc) as rn -from products_extended where email_support is null) where rn = 1 +select category, name, price, email_support, +row_number() over (partition by category order by price desc) as rn +from products_extended +where email_support is null) +where rn = 1 ), email_true as (select * from ( -select category, name, price, email_support, row_number() over (partition by category order by price desc) as rn -from products_extended where email_support is not null) where rn = 1 +select category, name, price, email_support, +row_number() over (partition by category order by price desc) as rn +from products_extended +where email_support is not null) +where rn = 1 ) select category, name, price, email_support from email_false union all select category, name, price, email_support from email_true order by category, price desc + +---------------------- Задание №2 (Переделал с двух оконок в одном запросе на СТЕ с одной оконкой внутри) +with get_data as ( +select name, category, price, +LEAD(price) OVER (PARTITION BY category order by price) AS next_price +from products_extended +) + +select name, category, price, next_price, +price - next_price AS diff +from get_data + +--------------------- Задание №3 +select category, name, price, +SUM(price) over (partition by category order by price) as cumulative_sales +from products_extended + +---------------------- Задание №4 +with get_data as ( +select category, name, price, AVG(price) over (partition by category) as avg_price +from products_extended +) +select category, name, price, avg_price, +case when price > avg_price then 'true' else 'false' end as is_above_avg +from get_data From 311f6b259beae97829e4ca6084a580e986dcf82c Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 7 Feb 2026 14:19:52 +0300 Subject: [PATCH 10/28] Pet project DDL&DML done --- aharlamcev/postgresql/Pet-projectsql.sql | 202 +++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 aharlamcev/postgresql/Pet-projectsql.sql diff --git a/aharlamcev/postgresql/Pet-projectsql.sql b/aharlamcev/postgresql/Pet-projectsql.sql new file mode 100644 index 0000000..8b1d51f --- /dev/null +++ b/aharlamcev/postgresql/Pet-projectsql.sql @@ -0,0 +1,202 @@ +create table users ( +id INT primary key, +name VARCHAR(50), +age INT, +email VARCHAR(50), +registration_date date +); + +INSERT INTO users (id, name, age, email, registration_date) +VALUES +(1, 'Alice', 25, 'alice@mail.com', '2023-01-10'), +(2, 'Bob', 30, 'bob@gmail.com', '2023-02-05'), +(3, 'Charlie', 22, 'charlie@mail.com', '2023-02-20'), +(4, 'Diana', 28, 'diana@mail.com', '2023-03-01'), +(5, 'Ethan', 35, 'ethan@gmail.com', '2023-03-10'), +(6, 'Frank', 29, 'frank@mail.com', '2023-01-05'), +(7, 'Grace', 26, 'grace@gmail.com', '2023-01-12'), +(8, 'Henry', 32, 'henry@mail.com', '2023-01-20'), +(9, 'Iris', 24, 'iris@gmail.com', '2023-02-10'), +(10, 'Jack', 27, 'jack@mail.com', '2023-04-15'), +(11, 'Kelly', 23, 'kelly@gmail.com', '2023-04-20'), +(12, 'Leo', 31, 'leo@mail.com', '2023-01-15'), +(13, 'Mia', 26, 'mia@gmail.com', '2023-01-18'), +(14, 'Nina', 28, 'nina@mail.com', '2023-01-08'), +(15, 'Oscar', 33, 'oscar@gmail.com', '2023-01-10'), +(16, 'Paul', 29, 'paul@mail.com', '2023-02-15'), +(17, 'Quinn', 24, 'quinn@gmail.com', '2023-03-20'), +(18, 'Rita', 27, 'rita@mail.com', '2023-04-01'), +(19, 'Sam', 30, 'sam@gmail.com', '2023-04-10'), +(20, 'Tina', 25, 'tina@mail.com', '2023-04-18'); + +create table courses ( +id INT primary key, +title VARCHAR(100), +category VARCHAR(50), +created_at date +); + +INSERT INTO courses (id, title, category, created_at) +VALUES +(1, 'SQL для начинающих', 'data', '2023-01-01'), +(2, 'Python для анализа данных', 'programming', '2023-01-15'), +(3, 'BI с нуля', 'business', '2023-03-01'), +(4, 'Excel для аналитиков', 'business', '2023-02-01'), +(5, 'Основы машинного обучения', 'data', '2023-03-15'); + + +create table lessons ( +id INT primary key, +course_id INT, +title VARCHAR(100), +duration_min INT, +foreign key (course_id) references courses(id) +); + +INSERT INTO lessons (id, course_id, title, duration_min) +VALUES +(1, 1, 'SELECT и FROM', 10), +(2, 1, 'JOIN', 15), +(3, 1, 'WHERE и фильтрация', 12), +(4, 1, 'Агрегации и GROUP BY', 18), +(5, 1, 'Подзапросы', 25), +(6, 2, 'Pandas основы', 20), +(7, 2, 'NumPy', 15), +(8, 2, 'Визуализация данных', 22), +(9, 3, 'Основы BI', 12), +(10, 3, 'Метрики и дашборды', 18), +(11, 3, 'Power BI введение', 20), +(12, 4, 'Формулы в Excel', 15), +(13, 4, 'Сводные таблицы', 18), +(14, 4, 'Графики и диаграммы', 14), +(15, 5, 'Введение в ML', 20), +(16, 5, 'Линейная регрессия', 30), +(17, 5, 'Классификация', 28), +(18, 5, 'Кластеризация', 25); + +create table enrollments ( +id INT primary key, +user_id INT, +course_id INT, +enrolled_at date, +foreign key (user_id) references users(id), +foreign key (course_id) references courses(id) +); + +INSERT INTO enrollments (id, user_id, course_id, enrolled_at) +VALUES +(1, 1, 1, '2023-01-15'), +(2, 1, 2, '2023-02-01'), +(3, 2, 1, '2023-01-20'), +(4, 3, 2, '2023-03-05'), +(5, 4, 3, '2023-04-01'), +(6, 6, 1, '2023-01-06'), +(7, 6, 2, '2023-01-10'), +(8, 6, 4, '2023-02-05'), +(9, 7, 1, '2023-01-13'), +(10, 7, 3, '2023-03-10'), +(11, 8, 1, '2023-01-22'), +(12, 8, 2, '2023-01-22'), +(13, 8, 3, '2023-01-22'), +(14, 9, 4, '2023-02-12'), +(15, 10, 1, '2023-04-16'), +(16, 11, 2, '2023-04-21'), +(17, 12, 1, '2023-01-16'), +(18, 13, 2, '2023-01-19'), +(19, 13, 4, '2023-02-20'), +(20, 14, 1, '2023-01-09'), +(21, 14, 2, '2023-01-09'), +(22, 14, 3, '2023-01-09'), +(23, 14, 4, '2023-02-01'), +(24, 14, 5, '2023-03-20'), +(25, 15, 1, '2023-01-11'), +(26, 15, 3, '2023-03-05'), +(27, 16, 2, '2023-02-16'), +(28, 16, 4, '2023-02-16'), +(29, 17, 3, '2023-03-22'), +(30, 17, 5, '2023-03-25'), +(31, 18, 1, '2023-04-02'), +(32, 19, 1, '2023-04-11'), +(33, 19, 2, '2023-04-11'), +(34, 20, 2, '2023-04-19'), +(35, 5, 5, '2023-03-20'), +(36, 1, 4, '2023-02-10'), +(37, 2, 3, '2023-03-15'), +(38, 3, 1, '2023-02-25'), +(39, 4, 2, '2023-03-10'), +(40, 6, 3, '2023-03-08'), +(41, 7, 2, '2023-02-01'), +(42, 9, 1, '2023-02-15'), +(43, 12, 3, '2023-03-10'), +(44, 15, 2, '2023-02-01'), +(45, 18, 4, '2023-04-05'); + +create table lesson_views ( +id INT primary key, +user_id INT, +lesson_id INT, +viewed_at timestamp, +foreign key (user_id) references users(id), +foreign key (lesson_id) references lessons(id) +); + +INSERT INTO lesson_views (id, user_id, lesson_id, viewed_at) +VALUES +(1, 1, 1, '2023-01-16 10:00:00'), +(2, 1, 2, '2023-01-16 10:15:00'), +(3, 1, 3, '2023-01-17 09:00:00'), +(4, 1, 4, '2023-01-17 09:30:00'), +(5, 1, 4, '2023-01-17 11:00:00'), +(6, 1, 4, '2023-01-18 10:00:00'), +(7, 1, 6, '2023-02-02 14:00:00'), +(8, 1, 12, '2023-02-15 10:00:00'), +(9, 1, 13, '2023-02-15 10:30:00'), +(10, 2, 1, '2023-01-21 09:00:00'), +(11, 2, 9, '2023-03-16 10:00:00'), +(12, 2, 10, '2023-03-16 10:30:00'), +(13, 3, 6, '2023-03-06 12:00:00'), +(14, 3, 1, '2023-02-26 11:00:00'), +(15, 3, 2, '2023-02-26 11:20:00'), +(16, 4, 9, '2023-04-02 10:00:00'), +(17, 4, 10, '2023-04-03 10:00:00'), +(18, 4, 6, '2023-03-12 14:00:00'), +(19, 4, 7, '2023-03-13 09:00:00'), +(20, 5, 15, '2023-03-21 10:00:00'), +(21, 5, 16, '2023-03-22 11:00:00'), +(22, 6, 1, '2023-01-07 10:00:00'), +(23, 6, 2, '2023-01-07 10:15:00'), +(24, 6, 3, '2023-01-08 09:00:00'), +(25, 6, 4, '2023-01-08 09:30:00'), +(26, 6, 5, '2023-01-09 10:00:00'), +(27, 6, 6, '2023-01-11 14:00:00'), +(28, 6, 7, '2023-01-12 10:00:00'), +(29, 6, 8, '2023-01-13 11:00:00'), +(30, 6, 12, '2023-02-06 09:00:00'), +(31, 6, 13, '2023-02-06 09:30:00'), +(32, 6, 14, '2023-02-07 10:00:00'), +(33, 6, 9, '2023-03-09 11:00:00'), +(34, 7, 1, '2023-01-14 10:00:00'), +(35, 7, 2, '2023-01-14 10:20:00'), +(36, 7, 3, '2023-01-15 09:00:00'), +(37, 7, 9, '2023-03-11 14:00:00'), +(38, 7, 10, '2023-03-11 14:30:00'), +(39, 9, 12, '2023-02-13 10:00:00'), +(40, 9, 13, '2023-02-13 10:30:00'), +(41, 9, 1, '2023-02-16 11:00:00'), +(42, 12, 1, '2023-01-17 10:00:00'), +(43, 12, 2, '2023-01-17 10:20:00'), +(44, 12, 1, '2023-04-10 11:00:00'), +(45, 12, 3, '2023-04-10 11:30:00'), +(46, 12, 9, '2023-03-12 10:00:00'), +(47, 13, 6, '2023-01-20 14:00:00'), +(48, 13, 7, '2023-01-21 10:00:00'), +(49, 13, 12, '2023-02-21 09:00:00'), +(50, 14, 1, '2023-01-09 08:00:00'), +(51, 14, 2, '2023-01-09 08:15:00'), +(52, 14, 3, '2023-01-10 10:00:00'), +(53, 14, 4, '2023-01-10 10:30:00'), +(54, 14, 5, '2023-01-11 09:00:00'), +(55, 14, 6, '2023-01-10 14:00:00'), +(56, 14, 7, '2023-01-11 10:00:00'), +(57, 14, 8, '2023-01-12 11:00:00'), +(58, 14, 9, '2023-01-10 08:00:00'); From 0bdc2ef4523263e9e3183464782ec6e6a29057c0 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 8 Feb 2026 12:55:07 +0300 Subject: [PATCH 11/28] =?UTF-8?q?fixed=20task=E2=84=964=20boolean?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aharlamcev/postgresql/WindowFunctionHomework.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aharlamcev/postgresql/WindowFunctionHomework.sql b/aharlamcev/postgresql/WindowFunctionHomework.sql index 0e16bf1..2cf8068 100644 --- a/aharlamcev/postgresql/WindowFunctionHomework.sql +++ b/aharlamcev/postgresql/WindowFunctionHomework.sql @@ -68,5 +68,5 @@ select category, name, price, AVG(price) over (partition by category) as avg_pri from products_extended ) select category, name, price, avg_price, -case when price > avg_price then 'true' else 'false' end as is_above_avg +case when price > avg_price then true else false end as is_above_avg from get_data From df8159a2872ec46afea9ace160bff0268d9a0c66 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 13 Feb 2026 16:10:48 +0300 Subject: [PATCH 12/28] deleted old homework --- aharlamcev/postgresql/BaseSQLhomework.sql | 28 -------- aharlamcev/postgresql/DMLhomework.sql | 52 -------------- aharlamcev/postgresql/Filtrationhomework.sql | 22 ------ .../postgresql/WindowFunctionHomework.sql | 72 ------------------- aharlamcev/postgresql/homeworkDDL.sql | 35 --------- aharlamcev/postgresql/sqlhomework.sql | 23 ------ 6 files changed, 232 deletions(-) delete mode 100644 aharlamcev/postgresql/BaseSQLhomework.sql delete mode 100644 aharlamcev/postgresql/DMLhomework.sql delete mode 100644 aharlamcev/postgresql/Filtrationhomework.sql delete mode 100644 aharlamcev/postgresql/WindowFunctionHomework.sql delete mode 100644 aharlamcev/postgresql/homeworkDDL.sql delete mode 100644 aharlamcev/postgresql/sqlhomework.sql diff --git a/aharlamcev/postgresql/BaseSQLhomework.sql b/aharlamcev/postgresql/BaseSQLhomework.sql deleted file mode 100644 index 92666f2..0000000 --- a/aharlamcev/postgresql/BaseSQLhomework.sql +++ /dev/null @@ -1,28 +0,0 @@ -select * from users - -select id, name, country from users -order by name; - -select id, name, country, created_at from users -where country = 'KZ' -order by created_at desc; - -select id, name from users -where email is null; - -select id, name from users -where email is not null; - -update users -set email = 'alice@mail.com' -where name = 'Alice'; -- в моей таблице ни у кого нет email, добавил чтобы посмотреть. - -select id, name, UPPER(email) as email_upper from users; - -select id, name, LOWER(email) as email_lower from users -where email is not null; - -select id, name, created_at from users -where created_at > '2024-01-11' -order by created_at desc -limit 2; diff --git a/aharlamcev/postgresql/DMLhomework.sql b/aharlamcev/postgresql/DMLhomework.sql deleted file mode 100644 index b50c436..0000000 --- a/aharlamcev/postgresql/DMLhomework.sql +++ /dev/null @@ -1,52 +0,0 @@ -select * from users - -insert into users (id, name, email, country, created_at) -values (1, 'Alice', null, 'KZ', '2026-01-17'); - -insert into users (id, name, email, country, created_at) -values (2, 'Bob', null, 'USA', '2026-01-17'); - -insert into users (id, name, email, country, created_at) -values (3, 'Charlie', null, 'RU', '2026-01-17'); - -select * from products - -insert into products (id, name, category, price, in_stock) -values (1, 'Mi Band 7', 'smartwatch', 49, true) - -insert into products (id, name, category, price, in_stock) -values (2, 'Surface Pro', 'tablet', 1299, true) - -insert into products (id, name, category, price, in_stock) -values (3, 'Iphone 15', 'smartphone', 999, true) - -insert into products (id, name, category, price, in_stock) -values (4, 'Logitech MX Master', 'mouse', 120, true) - -insert into orders (id, user_id, order_date, status) -values (1, 1, '2026-01-17', 'in delivery'); - -insert into orders (id, user_id, order_date, status) -values (2, 1, '2026-01-17', 'shipped'); - -insert into orders (id, user_id, order_date, status) -values (3, 2, '2026-01-17', 'preparing'); - -select * from order_items - -insert into order_items (order_id, product_id, quantity, price_at_purchase) -values (1,1, 2, 49) - -insert into order_items (order_id, product_id, quantity, price_at_purchase) -values (1, 2, 1, 1299) - -insert into order_items (order_id, product_id, quantity, price_at_purchase) -values (2, 3, 1, 999) - -insert into order_items (order_id, product_id, quantity, price_at_purchase) -values (3, 4, 2, 120) - -insert into order_items (order_id, product_id, quantity, price_at_purchase) -values (3, 1, 2, 49) - --- Сейчас уже понял, что можно после insert - values добавлять сразу в скобках несколько штук, но изначально делал так. \ No newline at end of file diff --git a/aharlamcev/postgresql/Filtrationhomework.sql b/aharlamcev/postgresql/Filtrationhomework.sql deleted file mode 100644 index b8d9407..0000000 --- a/aharlamcev/postgresql/Filtrationhomework.sql +++ /dev/null @@ -1,22 +0,0 @@ -select * from products - -select name, category, price, price * 1.3 as price_with_markup, price * 1.5 as price_with_vat -from products -where in_stock is true and category != 'smartwatch' and price between 100 and 1300; - -select name, price, price * 0.85 as price_with_discount -from products -where price < 100 or price > 1000; - -select id, name, category, price from products -where category in ('tablet', 'smartphone', 'mouse') and price > 100; - -select name, category, price from products -where name not ilike '%iphone%'; - -select name, category, price from products -where name ilike '%pro%'; - -select name, category, price from products -where name ilike '%mx%' -order by price desc; \ No newline at end of file diff --git a/aharlamcev/postgresql/WindowFunctionHomework.sql b/aharlamcev/postgresql/WindowFunctionHomework.sql deleted file mode 100644 index 2cf8068..0000000 --- a/aharlamcev/postgresql/WindowFunctionHomework.sql +++ /dev/null @@ -1,72 +0,0 @@ -create table products_extended ( -id INT primary key, -name VARCHAR(50) not null, -category VARCHAR(50) not null, -price INT, -in_stock BOOLEAN default true, -email_support VARCHAR(50) -); - -insert into products_extended (id, name, category, price, in_stock, email_support) -values (1, 'iPhone 14', 'smartphone', 799, true, 'iphone@apple.com'), -(2, 'MacBook Air', 'laptop', 1199, false, NULL), -(3, 'Galaxy S22', 'smartphone', 699, true, 'galaxy@support.com'), -(4, 'ThinkPad X1', 'laptop', 1399, true, 'thinkpad@lenovo.com'), -(5, 'iPad Pro', 'tablet', 999, false, 'ipad@apple.com'), -(6, 'Kindle Paperwhite', 'ebook_reader', 149, true, NULL), -(7, 'Mi Band 7', 'smartwatch', 49, true, 'miband@xiaomi.com'), -(8, 'Surface Pro', 'tablet', 1299, true, 'surface@microsoft.com'), -(9, 'Honor Pad X9', 'tablet', 219, true, 'honor@support.com'), -(10, 'Dell XPS 13', 'laptop', 1099, false, 'dell@support.com'); - -alter table products_extended -alter column price type DECIMAL(10, 2) - ------------------- Задание №1 (По нему ты говорил, что нечитаемо, объясни как переделать pls <3) -with email_false as (select * from -( -select category, name, price, email_support, -row_number() over (partition by category order by price desc) as rn -from products_extended -where email_support is null) -where rn = 1 -), - -email_true as (select * from -( -select category, name, price, email_support, -row_number() over (partition by category order by price desc) as rn -from products_extended -where email_support is not null) -where rn = 1 -) - -select category, name, price, email_support from email_false -union all -select category, name, price, email_support from email_true -order by category, price desc - ----------------------- Задание №2 (Переделал с двух оконок в одном запросе на СТЕ с одной оконкой внутри) -with get_data as ( -select name, category, price, -LEAD(price) OVER (PARTITION BY category order by price) AS next_price -from products_extended -) - -select name, category, price, next_price, -price - next_price AS diff -from get_data - ---------------------- Задание №3 -select category, name, price, -SUM(price) over (partition by category order by price) as cumulative_sales -from products_extended - ----------------------- Задание №4 -with get_data as ( -select category, name, price, AVG(price) over (partition by category) as avg_price -from products_extended -) -select category, name, price, avg_price, -case when price > avg_price then true else false end as is_above_avg -from get_data diff --git a/aharlamcev/postgresql/homeworkDDL.sql b/aharlamcev/postgresql/homeworkDDL.sql deleted file mode 100644 index 5e43015..0000000 --- a/aharlamcev/postgresql/homeworkDDL.sql +++ /dev/null @@ -1,35 +0,0 @@ -create table users ( -id int primary key, -name VARCHAR(100) not null, -email VARCHAR(100), -country VARCHAR(50), -crated_at date not null -) ; - -create table products ( -id int primary key, -name VARCHAR(100) not null, -category VARCHAR(50), -price DECIMAL(10, 2), -in_stock BOOLEAN default true -) ; - -create table orders ( -id int primary key, -user_id int, -order_date DATE not null, -status VARCHAR(20), -foreign key (user_id) references users(id) -) ; - -create table order_items ( -order_id int, -product_id int, -quantity int not null, -price_at_purchase DECIMAL(10, 2) not null, -foreign key (order_id) references orders(id), -foreign key (product_id) references products(id) -) ; - -alter table users -rename column crated_at to created_at; \ No newline at end of file diff --git a/aharlamcev/postgresql/sqlhomework.sql b/aharlamcev/postgresql/sqlhomework.sql deleted file mode 100644 index 4fb1078..0000000 --- a/aharlamcev/postgresql/sqlhomework.sql +++ /dev/null @@ -1,23 +0,0 @@ -create table products_extended ( -id INT primary key, -name VARCHAR(100) not null, -category VARCHAR(50), -price DECIMAL(10, 2), -in_stock BOOLEAN default true, -email_support VARCHAR(50) -); - -insert into products_extended (id, name, category, price, in_stock, email_support) -values (1, 'Mi Band 7', 'smartwatch', 49, true, 'miband@xiaomi.com'); - -insert into products_extended (id, name, category, price, in_stock, email_support) -values (2, 'Surface Pro', 'tablet', 1299, true, 'surface@microsoft.com'); - -select * from products_extended -- проверил как выглядит таблица - -alter table products_extended -add column rating DECIMAL(5, 2); - -truncate table products_extended; - -drop table products_extended From 4aa11c013629701ee6a5992f63ef7b844fd98f69 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 15 Feb 2026 15:30:39 +0300 Subject: [PATCH 13/28] All homework SQL2.0 done in one file --- aharlamcev/postgresql/SQL2.0FULL.sql | 523 +++++++++++++++++++++++++++ 1 file changed, 523 insertions(+) create mode 100644 aharlamcev/postgresql/SQL2.0FULL.sql diff --git a/aharlamcev/postgresql/SQL2.0FULL.sql b/aharlamcev/postgresql/SQL2.0FULL.sql new file mode 100644 index 0000000..7cc305b --- /dev/null +++ b/aharlamcev/postgresql/SQL2.0FULL.sql @@ -0,0 +1,523 @@ +----------------------------------------------------------- +--DDL +create table users ( +id INT primary key not null, +name VARCHAR(100), +age INT, +email VARCHAR(100), +country VARCHAR(50), +is_active BOOLEAN, +created_at DATE +); + +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 DATE not null, +status VARCHAR(20) +); + +create table order_items ( +order_id INT, +product_id INT, +quantity INT not null, +price_at_purchase DECIMAL(10, 2) not null, +primary key (order_id, product_id) +); + +alter table users +alter column created_at type timestamptz; + +-------------------------------------------------------------------------------------- +-- DML +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); + + +-------------------------------------------------------------------------------------------- +--BASE SQL +select id, name, country, created_at, email from users +order by created_at desc, name; + +select id, name, country from users +where country = 'US' -- 'UK' +order by name; + +select id, name, email from users +where email is not null +order by name; + +select distinct LOWER(email) as email_lower from users +where email is not null; + +select id, name, created_at from users +where created_at > '2024-01-11' +order by created_at desc +limit 2 offset 1; +------------------------------------------------------------------------------------------------------ +-- FILTRATION +select name, category, price, +price * 1.3 as price_with_markup, +price * 1.5 as price_with_vat from products +where in_stock is true +and category not in ('Гаджеты') +and price >= 100 and price <=1300; + +select name, price, +price * 0.85 as price_with_discount +from products +where price < 100 or price > 1000; + +select id, name, category, price from products +where category in ('Электроника') and price >= 15000; + +select name, category, price from products +where name not like '%iPhone%'; + +select * from products +where name ilike '%pro%'; + +--------------------------------------------------------------------------------------------------- +-- JOIN +-- 1 задание +select o.id as order_id, order_date, status, u.name as user_name, country from orders o +join users u on o.user_id = u.id; + +-- 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 o.id = oi.order_id +join products p on oi.product_id = p.id +where o.id = 1; + +-- 3 задание +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 o.id = oi.order_id +join products p on oi.product_id = p.id; + +-- 4 задание +select u.name as user_name, o.id as order_id, o.status from users u +left join orders o on u.id = o.user_id; + +-- 5 задание +select u.id as user_id, u.name as user_name from users u +left join orders o on u.id = o.user_id +where o.user_id is null; + +-- 6 задание + +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 o.id = oi.order_id +join products p on oi.product_id = p.id +where p.name = 'Фитнес‑браслет'; + +-- 7 задание + +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 o.id = oi.order_id +join products p on oi.product_id = p.id +where o.status = 'paid'; + +-- 8 задание + +select o.id, o.order_date, p.name as product_name, oi.quantity, oi.price_at_purchase from orders o +join order_items oi on o.id = oi.order_id +join products p on oi.product_id = p.id +where o.user_id in (select id from users where name = 'Alice'); + +-- 9 задание + +select o.id as order_id, o.user_id, o.status from orders o +left join order_items oi on o.id = oi.order_id +where oi.product_id is null; -- таких у нас заказов нет, во всех заказах есть товары. + +-------------------------------------------------------------------------------------------- +-- UNION +-- 1 задание +select id, name, is_active from users +where is_active is false +union +select id, name, is_active from users +where is_active is true +order by name; + +-- 2 задание +select id as order_id, user_id, order_date, +case when o.order_date < '2025-02-01' then 'old' else 'new' end as period +from orders o; +-- 3е задание не имеет смысла, т.к. все заказы покупались, там нечего соединять + +---------------------------------------------------------------------------------------------- +-- Agregation +-- 1 задание +select category, COUNT(*) as products_count from products +group by category +order by products_count desc; + +-- 2 задание +select order_id, SUM(quantity) as total_quantity, SUM(quantity * price_at_purchase) as order_revenue from order_items +group by order_id +order by order_revenue desc; + +-- 3 задание +select p.category, SUM(oi.quantity * oi.price_at_purchase) as category_revenue from products p +join order_items oi on oi.product_id = p.id +group by p.category +order by category_revenue desc; + +-- 4 задание +select order_id, SUM(quantity * price_at_purchase) as order_revenue from order_items oi +join orders o on oi.order_id = o.id +where o.status = 'paid' +group by oi.order_id +order by order_revenue desc; + +-- 5 задание +select p.category, SUM(oi.quantity * oi.price_at_purchase) as category_revenue from products p +join order_items oi on oi.product_id = p.id +group by p.category +having SUM(oi.quantity * oi.price_at_purchase) > 1000 +order by category_revenue desc; + +-- 6 задание +select country, COUNT(*) as active_users_count +from users +where is_active is true +group by country +having COUNT(*) >= 2 +order by active_users_count desc; + +-- 7 задание +select p.name, SUM(oi.quantity) as total_quantity_sold from products p +join order_items oi on oi.product_id = p.id +group by p.name +order by total_quantity_sold desc +limit 3; + +-- 8 задание + +select order_id, SUM(quantity * price_at_purchase) as order_revenue +from order_items +group by order_id +having SUM(quantity * price_at_purchase) < 10000 -- сделал меньше 10000 потому что заказов дешевле 100 нет. +order by order_revenue; + +-------------------------------------------------------------------------------------------------------------- +--Functions:date strings logic +-- 1 задание +select name, +created_at::date as created_date, +CURRENT_DATE - created_at::date as days_since_registration +from users +where CURRENT_DATE - created_at::date > 750 +order by days_since_registration desc; + +-- 2 задание +select name, LOWER(email) as email_clean, +substring(LOWER(email) from position('@' in email) + 1) as domain +from users +where email is not null +order by domain, name; + +-- 3 задание +select name, age, +case when age < 25 then 'young' + when age between 20 and 30 then 'adult' + else 'senior' + end as age_group +from users +order by age; + +-- 4 задание +with CTE as + (select name, created_at::date, + current_date - created_at::date as days_since_registration, + case when is_active = true then 'hot' + when current_date - created_at::date < 30 then 'hot' + else 'regular' + end as hot_flag + from users) +select * from CTE +where hot_flag = 'hot'; + +-- 5 задание +with CTE as + (select count(id) as total_users, + COUNT(email) as with_email, + (select count(*) from users where email is null) as without_email + from users) +select total_users, with_email, without_email, + ROUND(100.0 * without_email / total_users, 2) as percentage_no_email + from CTE; + + -- 6 задание + select name, + CURRENT_DATE - created_at::date as days_since_registration, + case + when CURRENT_DATE - created_at::date <= 720 then 'new' + when CURRENT_DATE - created_at::date BETWEEN 721 and 750 then 'middle' + else 'old' + end as tenure_group + from users + order by days_since_registration; + + ---------------------------------------------------------------------------------------------------- + --Subquery/CTE + -- 1 задание +select name +from users +where id in (select distinct user_id from orders) +order by name; + +-- 2 задание +select id, name, email +from users u +where not exists ( +select user_id +from orders o +where o.user_id = u.id) + +-- 3 задание +select name, +(select COUNT(*) orders_count from orders o +where o.user_id = u.id) +from users u +order by orders_count desc, name; + +-- 4 задание +with CTE as ( + select user_id, SUM(quantity * price_at_purchase) as total_revenue + from orders o + join order_items oi on o.id = oi.order_id + group by user_id + ) +select u.name, c.total_revenue from users u +join CTE c on u.id = c.user_id +order by c.total_revenue desc; + +-- 5 задание +with CTE as ( + select product_id, SUM(quantity * price_at_purchase) as product_revenue + from order_items + group by product_id + ) +select p.name as product_name, p.category, c.product_revenue from CTE c +join products p on c.product_id = p.id +order by c.product_revenue desc +limit 3; + +-- 6 задание +with CTE as ( + select o.user_id, SUM(quantity * price_at_purchase) as total_revenue from orders o + join order_items oi on o.id = oi.order_id + group by o.user_id + ) +select u.name, u.email, c.total_revenue from users u +join CTE c on u.id = c.user_id +where u.is_active is true +and c.total_revenue > 10000; + +-- 7 задание + +with CTE as ( + select order_id, SUM(quantity * price_at_purchase) as order_revenue + from order_items oi + join orders o on oi.order_id = o.id + where o.status = 'paid' + group by order_id + ) +select * from CTE +where order_revenue < 10000; + +--------------------------------------------------------------------------------------------- +--WINDOW FUNCTIONS +-- 1 задание +select u.id as user_id, u.name, o.id as order_id, o.order_date, +row_number() over (partition by o.user_id order by o.order_date) as order_number_for_user +from users u +join orders o on u.id = o.user_id; + +-- 2 задание +with CTE as ( + select u.id as user_id, u.name as user_name, order_id, o.order_date, SUM(quantity * price_at_purchase) as order_revenue + from order_items oi + join orders o on oi.order_id = o.id + join users u on o.user_id = u.id + group by u.id, u.name, order_id, o.order_date + order by user_id + ) +select user_id, user_name, order_id, order_date, order_revenue, +SUM(order_revenue) over (partition by user_id order by order_date) as running_revenue_for_user +from CTE + +-- 3 задание +with CTE as ( + select u.id as user_id, u.name as user_name, SUM(quantity * price_at_purchase) as total_revenue + from order_items oi + join orders o on oi.order_id = o.id + join users u on o.user_id = u.id + group by u.id, u.name + ) +select user_name, total_revenue, +RANK() over (order by total_revenue desc) as revenue_rank, +dense_rank() over (order by total_revenue desc) as dense_revenue_rank +from CTE; + + +-- 4 задание +select u.name, o.id as order_id, order_date, +first_value(o.order_date) over (partition by user_id order by order_date) as first_order_date, +last_value(o.order_date) over (partition by user_id order by order_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as last_order_date +from orders o +join users u on u.id = o.user_id; + + +-- 5 задание +select u.name as user_name, o.id as order_id, +COUNT(*) over (partition by u.id) as orders_per_user +from users u +join orders o on u.id = o.user_id; + +-- 6 задание +with CTE as ( + select u.id as user_id, u.name as user_name, order_id, o.order_date as order_date, + SUM(quantity * price_at_purchase) as order_revenue + from order_items oi + join orders o on oi.order_id = o.id + join users u on o.user_id = u.id + group by u.id, u.name, order_id, o.order_date + order by user_id + ) +select user_name, order_id, order_date, order_revenue, +LAG(order_revenue) over (partition by user_id order by order_date) as prev_order_revenue +from CTE; + +-- 7 задание +with CTEa as ( + select product_id, + o.order_date::date as order_date, + SUM(quantity * price_at_purchase) as daily_category_revenue + from order_items oi + join orders o on oi.order_id = o.id + group by product_id, order_date + order by oi.product_id + ), + CTEb as ( + select p.category, order_date, daily_category_revenue + from CTEa a + join products p on a.product_id = p.id + ) +select category, order_date, daily_category_revenue, +SUM(daily_category_revenue) over (partition by category order by order_date) as running_category_revenue +from CTEb; + +----------------------------------------------------------------------------------------------------------- +-- VIEW and MATERIALIZED VIEW +-- 1 задание +create MATERIALIZED view mv_category_revenue +as + select p.category, SUM(quantity * price_at_purchase) as total_revenue + from products p + join order_items oi on oi.product_id = p.id + join orders o on oi.order_id = o.id and o.status = 'paid' + group by p.category + order by total_revenue desc +; + +-- 2 задание +create materialized view +as + select u.id, u.name, COUNT(o.id) as order_count + from users u + join orders o on u.id = o.user_id and o.status = 'paid' + group by u.id, u.name + order by order_count desc +; + +-- 3 задание +create materialized view mv_daily_revenue +as + select order_date::date as sales_date, SUM(quantity * price_at_purchase) as daily_revenue from orders o + join order_items oi on o.id = oi.order_id + where o.status = 'paid' + group by sales_date + order by sales_date +; + +-- 4 задание +refresh materialized view mv_daily_revenue; + +-- В 1 случае витрину можно обновлять 1 раз в день в 10:00 или 2 раза в день в 10:00 и в 22:00 +-- Во 2 случае витрину нужно обновлять несколько раз в день, думаю каждые часа 2-3 то есть в 8 в 10 в 12 и тд. + + + + + + + + + + + + + + + + + From 87ba57befe7b54dae8889e7ae059c107503c7561 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 16 Feb 2026 11:05:00 +0300 Subject: [PATCH 14/28] FIXED --- aharlamcev/postgresql/SQL2.0FULL.sql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aharlamcev/postgresql/SQL2.0FULL.sql b/aharlamcev/postgresql/SQL2.0FULL.sql index 7cc305b..c44e8e7 100644 --- a/aharlamcev/postgresql/SQL2.0FULL.sql +++ b/aharlamcev/postgresql/SQL2.0FULL.sql @@ -23,6 +23,7 @@ id INT primary key, user_id INT, order_date DATE not null, status VARCHAR(20) +FOREIGN KEY (user_id) REFERENCES users(id) ); create table order_items ( @@ -31,6 +32,7 @@ product_id INT, quantity INT not null, price_at_purchase DECIMAL(10, 2) not null, primary key (order_id, product_id) +FOREIGN KEY () ); alter table users @@ -276,7 +278,7 @@ order by domain, name; -- 3 задание select name, age, -case when age < 25 then 'young' +case when age < 20 then 'young' when age between 20 and 30 then 'adult' else 'senior' end as age_group From 0c961319b9745adcb91eb4e2636bc45948a56f17 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 16 Feb 2026 13:16:37 +0300 Subject: [PATCH 15/28] PET-project 1st task completed --- aharlamcev/postgresql/Pet-projectsql.sql | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/aharlamcev/postgresql/Pet-projectsql.sql b/aharlamcev/postgresql/Pet-projectsql.sql index 8b1d51f..d9b0c35 100644 --- a/aharlamcev/postgresql/Pet-projectsql.sql +++ b/aharlamcev/postgresql/Pet-projectsql.sql @@ -200,3 +200,38 @@ VALUES (56, 14, 7, '2023-01-11 10:00:00'), (57, 14, 8, '2023-01-12 11:00:00'), (58, 14, 9, '2023-01-10 08:00:00'); + + +--------------------------------------------------------- +-- 1 задание Активные пользователи + +create materialized view user_activity_summary AS +with enroll_count as ( + select u.id as user_id, u.name as user_name, + COUNT(e.course_id) as enrollment_count + from users u + join enrollments e on u.id = e.user_id + group by u.id, u.name + ), +viewed_count as ( + select ec.user_id, ec.user_name, enrollment_count, + COUNT(distinct lv.lesson_id) as viewed_lessons_count, + MIN(lv.viewed_at) as first_view, + MAX(lv.viewed_at) as last_view + from enroll_count ec + left join lesson_views lv on ec.user_id = lv.user_id + group by ec.user_id, ec.user_name, enrollment_count + ), +possible_lessons as ( + select u.id as user_id, COUNT(l.id) as poss_lessons + from users u + left join enrollments e on u.id = e.user_id + left join lessons l on e.course_id = l.course_id + group by u.id + ) +select vc.user_id, user_name, enrollment_count, viewed_lessons_count, first_view, last_view, +ROUND(100.0 * viewed_lessons_count / pl.poss_lessons, 2) as engagement_rate +from viewed_count vc +left join possible_lessons pl on vc.user_id = pl.user_id +; + From 0efca05db5aee0be461d64658b74ae87e341d64f Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 17 Feb 2026 06:41:34 +0300 Subject: [PATCH 16/28] NOT NULL added into users table --- aharlamcev/postgresql/Pet-projectsql.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aharlamcev/postgresql/Pet-projectsql.sql b/aharlamcev/postgresql/Pet-projectsql.sql index d9b0c35..d6cdd9d 100644 --- a/aharlamcev/postgresql/Pet-projectsql.sql +++ b/aharlamcev/postgresql/Pet-projectsql.sql @@ -1,8 +1,8 @@ create table users ( id INT primary key, -name VARCHAR(50), +name VARCHAR(50) NOT NULL, age INT, -email VARCHAR(50), +email VARCHAR(50) NOT NULL, registration_date date ); From 0c4ad4965d11717a5c79484629b04631e71dff00 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 17 Feb 2026 15:08:15 +0300 Subject: [PATCH 17/28] PET 2nd task completed --- aharlamcev/postgresql/Pet-projectsql.sql | 40 +++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/aharlamcev/postgresql/Pet-projectsql.sql b/aharlamcev/postgresql/Pet-projectsql.sql index d6cdd9d..071765c 100644 --- a/aharlamcev/postgresql/Pet-projectsql.sql +++ b/aharlamcev/postgresql/Pet-projectsql.sql @@ -234,4 +234,42 @@ ROUND(100.0 * viewed_lessons_count / pl.poss_lessons, 2) as engagement_rate from viewed_count vc left join possible_lessons pl on vc.user_id = pl.user_id ; - + +------------------------------------------------------------------------------------------------------------------ +-- 2 задание Эффективность курсов + +create materialized view course_summary AS + with lessons_per_course as ( + select c.id as course_id, c.title as course_title, + COUNT(distinct e.user_id) as unique_users, + COUNT(distinct l.id) as lessons_count + from courses c + left join enrollments e on c.id = e.course_id + join lessons l on e.course_id = l.course_id + group by c.id, c.title + ), + course_views as ( + select l.course_id, COUNT(lv.id) as total_views + from lesson_views lv + join lessons l on lv.lesson_id = l.id + group by l.course_id + ), + view_date as ( + select l.course_id, + MIN(lv.viewed_at) as first_viewed_at, + MAX(lv.viewed_at) as last_viewed_at + from lessons l + join lesson_views lv on l.id = lv.lesson_id + group by l.course_id + ) + select lpc.course_id, lpc.course_title, lpc.unique_users, lpc.lessons_count, + ROUND(1.00 * cv.total_views / lpc.unique_users, 2) as avg_views_per_user, + vd.first_viewed_at, + vd.last_viewed_at + from lessons_per_course lpc + join course_views cv on lpc.course_id = cv.course_id + left join view_date vd on cv.course_id = vd.course_id + order by course_id +; + + From 1fa2d88bf2e1801df01d5fad411680fe8e18f4b0 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 18 Feb 2026 14:41:23 +0300 Subject: [PATCH 18/28] PET project task 3 completed --- aharlamcev/postgresql/Pet-projectsql.sql | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/aharlamcev/postgresql/Pet-projectsql.sql b/aharlamcev/postgresql/Pet-projectsql.sql index 071765c..bc21d74 100644 --- a/aharlamcev/postgresql/Pet-projectsql.sql +++ b/aharlamcev/postgresql/Pet-projectsql.sql @@ -272,4 +272,22 @@ create materialized view course_summary AS order by course_id ; +-------------------------------------------------------------------------------------------------- +-- 3 задание Общая отчетность по взаимодействию +create materialized view platform_summary as +with total_counts as ( + select COUNT(id) as total_users, + (select COUNT(id) from courses) as total_courses, + (select COUNT(id) from lessons) as total_lessons, + (select COUNT(id) from lesson_views) as total_views, + (select COUNT(distinct user_id) from lesson_views) as users_with_views + from users + ) +SELECT total_users, total_courses, total_lessons, users_with_views, +ROUND(1.00 * total_lessons / total_courses, 2) as avg_lessons_per_course, +ROUND(1.00 * total_views / total_lessons, 2) as avg_views_per_lesson +from total_counts +; + + From 93ae8af223a66b83d75e37b0076d9a76c8c055f1 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 19 Feb 2026 14:31:52 +0300 Subject: [PATCH 19/28] PET 4th task completed --- aharlamcev/postgresql/Pet-projectsql.sql | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/aharlamcev/postgresql/Pet-projectsql.sql b/aharlamcev/postgresql/Pet-projectsql.sql index bc21d74..1fb75f6 100644 --- a/aharlamcev/postgresql/Pet-projectsql.sql +++ b/aharlamcev/postgresql/Pet-projectsql.sql @@ -289,5 +289,38 @@ ROUND(1.00 * total_views / total_lessons, 2) as avg_views_per_lesson from total_counts ; +----------------------------------------------------------------------------------------------------- +-- 4 Задание Когортный анализ пользователей +create materialized view user_cohort_analysis AS +with needed_users as ( + select distinct u.id as user_id, u.registration_date as reg_date, e.course_id, lv.id as view_id, + lv.lesson_id as viewed_lesson_id, + FIRST_VALUE(lv.viewed_at) over (partition by lv.user_id order by lv.viewed_at) as first_view_date, + e.user_id as enrolled_users, + lv.user_id as active_users + from users u + left join enrollments e on u.id = e.user_id + left join lesson_views lv on e.user_id = lv.user_id + order by user_id + ), +CTE as ( + select + TO_CHAR(reg_date, 'YYYY-MM') as cohort_month, + COUNT(distinct user_id) as users_in_cohort, + COUNT(distinct enrolled_users) as enrolled_users, + COUNT(distinct active_users) as active_users, + COUNT(course_id) as courses_count, + extract('days' from AVG(first_view_date - reg_date)) as avg_time_to_first_view + from needed_users + where date_trunc('month', reg_date)::date = '2023-03-01' + group by cohort_month + ) +select cohort_month, users_in_cohort, enrolled_users, active_users, +ROUND(100.0 * active_users / users_in_cohort, 2) as retention_rate, +courses_count / users_in_cohort as avg_courses_per_user, +avg_time_to_first_view +from CTE +; + From 1f660822715ef71935574b75299f38fa64178a91 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 20 Feb 2026 15:13:14 +0300 Subject: [PATCH 20/28] PET 5th task completed --- aharlamcev/postgresql/Pet-projectsql.sql | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/aharlamcev/postgresql/Pet-projectsql.sql b/aharlamcev/postgresql/Pet-projectsql.sql index 1fb75f6..4bf94af 100644 --- a/aharlamcev/postgresql/Pet-projectsql.sql +++ b/aharlamcev/postgresql/Pet-projectsql.sql @@ -322,5 +322,40 @@ avg_time_to_first_view from CTE ; +------------------------------------------------------------------------------------------------------------------ +-- 5 Задание Популярность курсов +create materialized view lesson_popularity_ranking AS +with lessons_in_courses as ( + select l.id as lesson_id, l.title as lesson_title, c.title as course_title, + COUNT(e.user_id) as enrolled_users + from lessons l + join courses c on l.course_id = c.id + join enrollments e on e.course_id = c.id + group by l.id, l.title, c.title + order by lesson_id + ), +views_cte as ( + select lic.lesson_id, + COUNT(lv.id) as total_views, + COUNT(distinct lv.user_id) as unique_viewers, + 1.00 * COUNT(lv.id) / COUNT(distinct lv.user_id) as avg_views_per_user, + COUNT(lic.enrolled_users) as enrolled_to_course + from lessons_in_courses lic + join lesson_views lv on lic.lesson_id = lv.lesson_id + group by lic.lesson_id + ) +select lic.lesson_id, lic.lesson_title, lic.course_title, +vc.total_views, +vc.unique_viewers, +vc.avg_views_per_user, +dense_rank() OVER (ORDER BY vc.total_views desc) as popularity_rank, +ROUND(100.0 * unique_viewers / enrolled_to_course, 2) as completion_rate  +from lessons_in_courses lic +join views_cte vc on lic.lesson_id = vc.lesson_id +; +-- Единственный момент в том, что в итоговом MV нет уроков и курсов без просмотров, +--то есть тут только те уроки, у которых есть хотя бы 1 просмотр. +-- Я не смог разобраться с NULL после LEFT JOIN таблиц и выдывало ошибку деления на 0 при подсчете completion_rate + From a109cadca200fe5e9bed81672bcb0bb57a83816a Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 23 Feb 2026 13:22:24 +0300 Subject: [PATCH 21/28] Added LEFT JOIN and NULLIF to Task 5 --- aharlamcev/postgresql/Pet-projectsql.sql | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/aharlamcev/postgresql/Pet-projectsql.sql b/aharlamcev/postgresql/Pet-projectsql.sql index 4bf94af..a7cee09 100644 --- a/aharlamcev/postgresql/Pet-projectsql.sql +++ b/aharlamcev/postgresql/Pet-projectsql.sql @@ -324,7 +324,7 @@ from CTE ------------------------------------------------------------------------------------------------------------------ -- 5 Задание Популярность курсов -create materialized view lesson_popularity_ranking AS +create materialized view lesson_popularity_ranking as with lessons_in_courses as ( select l.id as lesson_id, l.title as lesson_title, c.title as course_title, COUNT(e.user_id) as enrolled_users @@ -338,24 +338,22 @@ views_cte as ( select lic.lesson_id, COUNT(lv.id) as total_views, COUNT(distinct lv.user_id) as unique_viewers, - 1.00 * COUNT(lv.id) / COUNT(distinct lv.user_id) as avg_views_per_user, + 1.00 * COUNT(lv.id) / nullif(COUNT(distinct lv.user_id), 0) as avg_views_per_user, COUNT(lic.enrolled_users) as enrolled_to_course from lessons_in_courses lic - join lesson_views lv on lic.lesson_id = lv.lesson_id + left join lesson_views lv on lic.lesson_id = lv.lesson_id group by lic.lesson_id ) select lic.lesson_id, lic.lesson_title, lic.course_title, vc.total_views, vc.unique_viewers, -vc.avg_views_per_user, +coalesce(vc.avg_views_per_user, 0), dense_rank() OVER (ORDER BY vc.total_views desc) as popularity_rank, -ROUND(100.0 * unique_viewers / enrolled_to_course, 2) as completion_rate  +ROUND(100.0 * unique_viewers / enrolled_to_course, 2) as completion_rate from lessons_in_courses lic join views_cte vc on lic.lesson_id = vc.lesson_id ; --- Единственный момент в том, что в итоговом MV нет уроков и курсов без просмотров, ---то есть тут только те уроки, у которых есть хотя бы 1 просмотр. --- Я не смог разобраться с NULL после LEFT JOIN таблиц и выдывало ошибку деления на 0 при подсчете completion_rate + From 4d56aa1f5b92082564bcbb9f02e733447e85b0fc Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 23 Feb 2026 15:02:11 +0300 Subject: [PATCH 22/28] Pet 6th task completed --- aharlamcev/postgresql/Pet-projectsql.sql | 95 +++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/aharlamcev/postgresql/Pet-projectsql.sql b/aharlamcev/postgresql/Pet-projectsql.sql index a7cee09..1621bf6 100644 --- a/aharlamcev/postgresql/Pet-projectsql.sql +++ b/aharlamcev/postgresql/Pet-projectsql.sql @@ -353,7 +353,100 @@ ROUND(100.0 * unique_viewers / enrolled_to_course, 2) as completion_rate from lessons_in_courses lic join views_cte vc on lic.lesson_id = vc.lesson_id ; - +----------------------------------------------------------------------------------------------- +-- 6 Задания Воронка Конверсии +create materialized view conversion_funnel AS +with course_lessons as ( + select c.id as course_id, c.title as course_title, + COUNT(l.id) as total_lessons + from courses c + join lessons l on l.course_id = c.id + group by c.id, c.title + ), +registered_users as ( + select COUNT(distinct id) as total_users + from users + ), +enrolled_users as ( + select e.course_id, + COUNT(distinct e.user_id) as enrolled_count + from enrollments e + group by e.course_id + ), +started_users as ( + select l.course_id, + COUNT(distinct lv.user_id) as started_count + from lessons l + join lesson_views lv on l.id = lv.lesson_id + group by l.course_id + ), +user_progress as ( + select l.course_id, lv.user_id, + COUNT(distinct lv.lesson_id) as viewed_lessons + from lesson_views lv + join lessons l on lv.lesson_id = l.id + group by l.course_id, lv.user_id + ), +mid_progress_users as ( + select up.course_id, + COUNT(distinct up.user_id) as mid_progress_count + from user_progress up + join course_lessons cl on up.course_id = cl.course_id + where up.viewed_lessons >= cl.total_lessons * 0.5 + group by up.course_id + ), +completed_users as ( + select up.course_id, + COUNT(distinct up.user_id) as completed_count + from user_progress up + join course_lessons cl on up.course_id = cl.course_id + where up.viewed_lessons >= cl.total_lessons + group by up.course_id + ), +funnel_stages as ( + select cl.course_id, cl.course_title, + 'registered' as stage_name, + ru.total_users as users_count, + 1 as stage_order + from course_lessons cl + cross join registered_users ru + union all + select cl.course_id, cl.course_title, + 'enrolled' as stage_name, + eu.enrolled_count as users_count, + 2 as stage_order + from course_lessons cl + left join enrolled_users eu on cl.course_id = eu.course_id + union all + select cl.course_id, cl.course_title, + 'started' as stage_name, + su.started_count as users_count, + 3 as stage_order + from course_lessons cl + left join started_users su on cl.course_id = su.course_id + union all + select cl.course_id, cl.course_title, + 'mid_progress' as stage_name, + coalesce(mpu.mid_progress_count, 0) as users_count, + 4 as stage_order + from course_lessons cl + left join mid_progress_users mpu on cl.course_id = mpu.course_id + union all + select cl.course_id, cl.course_title, + 'completed' as stage_name, + coalesce(cu.completed_count, 0) as users_count, + 5 as stage_order + from course_lessons cl + left join completed_users cu on cl.course_id = cu.course_id + ) + select course_id, course_title, stage_name, users_count, + ROUND(100.0 * users_count / NULLIF(LAG(users_count) over (partition by course_id order by stage_order), 0), 2) + as conversion_from_previous, + ROUND(100.0 * users_count / NULLIF(FIRST_VALUE(users_count) over (partition by course_id order by stage_order), 0), 2) + as conversion_from_start + from funnel_stages +; +-- Признаюсь 6-е задание сделал с помощью нейросети, потому что сам вообще никак к нему подобраться не мог. From 9dedbfc3eb258c863f129d9368221f752c504f7d Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 23 Feb 2026 15:06:03 +0300 Subject: [PATCH 23/28] PET 2nd task fixed --- aharlamcev/postgresql/Pet-projectsql.sql | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/aharlamcev/postgresql/Pet-projectsql.sql b/aharlamcev/postgresql/Pet-projectsql.sql index 1621bf6..98debeb 100644 --- a/aharlamcev/postgresql/Pet-projectsql.sql +++ b/aharlamcev/postgresql/Pet-projectsql.sql @@ -237,7 +237,6 @@ left join possible_lessons pl on vc.user_id = pl.user_id ------------------------------------------------------------------------------------------------------------------ -- 2 задание Эффективность курсов - create materialized view course_summary AS with lessons_per_course as ( select c.id as course_id, c.title as course_title, @@ -249,26 +248,20 @@ create materialized view course_summary AS group by c.id, c.title ), course_views as ( - select l.course_id, COUNT(lv.id) as total_views - from lesson_views lv - join lessons l on lv.lesson_id = l.id - group by l.course_id - ), - view_date as ( - select l.course_id, + select l.course_id, + COUNT(lv.id) as total_views, MIN(lv.viewed_at) as first_viewed_at, MAX(lv.viewed_at) as last_viewed_at - from lessons l - join lesson_views lv on l.id = lv.lesson_id + from lesson_views lv + join lessons l on lv.lesson_id = l.id group by l.course_id ) select lpc.course_id, lpc.course_title, lpc.unique_users, lpc.lessons_count, ROUND(1.00 * cv.total_views / lpc.unique_users, 2) as avg_views_per_user, - vd.first_viewed_at, - vd.last_viewed_at + cv.first_viewed_at, + cv.last_viewed_at from lessons_per_course lpc join course_views cv on lpc.course_id = cv.course_id - left join view_date vd on cv.course_id = vd.course_id order by course_id ; From c95a867e13b3e892e8520d009c9e135eb5e43ad0 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 24 Feb 2026 14:58:16 +0300 Subject: [PATCH 24/28] PET Extra Tasks completed --- aharlamcev/postgresql/Pet-projectsql.sql | 31 ++++++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/aharlamcev/postgresql/Pet-projectsql.sql b/aharlamcev/postgresql/Pet-projectsql.sql index 98debeb..7ad986c 100644 --- a/aharlamcev/postgresql/Pet-projectsql.sql +++ b/aharlamcev/postgresql/Pet-projectsql.sql @@ -283,7 +283,7 @@ from total_counts ; ----------------------------------------------------------------------------------------------------- --- 4 Задание Когортный анализ пользователей +-- 4 Задание Когортный анализ пользователей (Для каждого месяца регистрации) create materialized view user_cohort_analysis AS with needed_users as ( select distinct u.id as user_id, u.registration_date as reg_date, e.course_id, lv.id as view_id, @@ -305,7 +305,6 @@ CTE as ( COUNT(course_id) as courses_count, extract('days' from AVG(first_view_date - reg_date)) as avg_time_to_first_view from needed_users - where date_trunc('month', reg_date)::date = '2023-03-01' group by cohort_month ) select cohort_month, users_in_cohort, enrolled_users, active_users, @@ -340,7 +339,7 @@ views_cte as ( select lic.lesson_id, lic.lesson_title, lic.course_title, vc.total_views, vc.unique_viewers, -coalesce(vc.avg_views_per_user, 0), +coalesce(vc.avg_views_per_user, 0) as avg_views_per_user, dense_rank() OVER (ORDER BY vc.total_views desc) as popularity_rank, ROUND(100.0 * unique_viewers / enrolled_to_course, 2) as completion_rate from lessons_in_courses lic @@ -441,5 +440,27 @@ funnel_stages as ( ; -- Признаюсь 6-е задание сделал с помощью нейросети, потому что сам вообще никак к нему подобраться не мог. - - +----------------------------------------------------------------------------------------------------------------- +-- Доп. Задание №1 Анализ drop-off точек +select course_id, stage_name, users_count, +100 - conversion_from_previous as lost_precentage +from conversion_funnel +where stage_name = 'started' +order by lost_precentage desc +; +-------------------------------------------------------------------------------------------------------------------- +-- Доп. Задание №2 Топ-3 урока с повторными просмотрами +select lesson_id +from lesson_popularity_ranking +where avg_views_per_user > 1 +limit 3 +; +--------------------------------------------------------------------------------------------------------------------- +-- Доп. Задание №3 Лучшая когорта по retention +select cohort_month, retention_rate +from user_cohort_analysis +order by retention_rate desc +limit 2 +; +-- В нашем случае два месяца с одинаковыми лучшими показателями retention это 2023-01 и 2023-02. Это является следствием того, что у нас +-- наибольшее количество зарегистрированных пользователей именно в эти месяцы, а именно 2023-01 = 40%, а 2023-02 = 20%, соотвественно 60% пользователей были зарегистрированы в эти месяцы. \ No newline at end of file From ace9b8b292636e5e4491e6ea694d4c0a9ad7c9a7 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 26 Feb 2026 15:17:39 +0300 Subject: [PATCH 25/28] Task 2 fixed --- aharlamcev/PET-project_task2 | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 aharlamcev/PET-project_task2 diff --git a/aharlamcev/PET-project_task2 b/aharlamcev/PET-project_task2 new file mode 100644 index 0000000..0de3482 --- /dev/null +++ b/aharlamcev/PET-project_task2 @@ -0,0 +1,26 @@ +CREATE MATERIALIZED VIEW platform_summary AS +with users_counts as ( + select + COUNT(distinct u.id) as total_users, + COUNT(distinct lv.user_id) as users_with_views + from users u + left join lesson_views lv on lv.user_id = u.id + ), +courses_lessons_count as ( + select COUNT(distinct c.id) as total_courses, + COUNT(distinct l.id) as total_lessons + from courses c + left join lessons l on l.course_id = c.id + ), +views_count as ( + select COUNT(distinct lv.lesson_id) as lessons_with_views, + COUNT(distinct lv.id) as total_views + from lesson_views lv + ) +select uc.total_users, clc.total_courses, clc.total_lessons, uc.users_with_views, +ROUND(1.00 * clc.total_lessons / nullif(clc.total_courses, 0), 2) as avg_lessons_per_course, +ROUND(1.00 * vc.total_views / nullif(clc.total_lessons, 0), 2) as avg_views_per_lesson +from users_counts uc +cross join courses_lessons_count clc +cross join views_count vc +; \ No newline at end of file From 5854cdbd21bc290f8985cfe807822cc339e0e6f3 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 26 Feb 2026 15:21:31 +0300 Subject: [PATCH 26/28] Name changed to task3 --- aharlamcev/{PET-project_task2 => PET-project_task3} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename aharlamcev/{PET-project_task2 => PET-project_task3} (100%) diff --git a/aharlamcev/PET-project_task2 b/aharlamcev/PET-project_task3 similarity index 100% rename from aharlamcev/PET-project_task2 rename to aharlamcev/PET-project_task3 From de4a0fa2ec2c560455bdfea071f15d6f513fa21c Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 27 Feb 2026 15:31:56 +0300 Subject: [PATCH 27/28] PET task 4 fixed --- aharlamcev/PET-project_task4 | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 aharlamcev/PET-project_task4 diff --git a/aharlamcev/PET-project_task4 b/aharlamcev/PET-project_task4 new file mode 100644 index 0000000..5cb8fcd --- /dev/null +++ b/aharlamcev/PET-project_task4 @@ -0,0 +1,26 @@ +with needed_users as ( + select distinct u.id as user_id, + u.registration_date as reg_date, e.course_id, lv.id as view_id, + lv.lesson_id as viewed_lesson_id, + FIRST_VALUE(lv.viewed_at) over (partition by lv.user_id order by lv.viewed_at) as first_view_date + from users u + left join enrollments e on u.id = e.user_id + left join lesson_views lv on e.user_id = lv.user_id + order by user_id + ), +CTE as ( + select + TO_CHAR(reg_date, 'YYYY-MM') as cohort_month, + COUNT(distinct user_id) as users_in_cohort, + COUNT(distinct case when user_id in (select user_id from enrollments) then user_id end) as enrolled_users, + COUNT(distinct case when user_id in (select user_id from lesson_views) then user_id end) as active_users, + COUNT(course_id) as courses_count, + extract('days' from AVG(first_view_date - reg_date)) as avg_time_to_first_view + from needed_users + group by cohort_month + ) +select cohort_month, users_in_cohort, enrolled_users, active_users, +ROUND(100.0 * active_users / users_in_cohort, 2) as retention_rate, +courses_count::numeric / users_in_cohort as avg_courses_per_user, +avg_time_to_first_view +from CTE From cd4e5335aa0564050ec477057ae4186a03c2bce4 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 28 Feb 2026 16:07:09 +0300 Subject: [PATCH 28/28] PET task 4 finished --- aharlamcev/PET-project_task4 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aharlamcev/PET-project_task4 b/aharlamcev/PET-project_task4 index 5cb8fcd..d25c088 100644 --- a/aharlamcev/PET-project_task4 +++ b/aharlamcev/PET-project_task4 @@ -1,3 +1,4 @@ +CREATE MATERIALIZED VIEW users_cohort_analysis AS with needed_users as ( select distinct u.id as user_id, u.registration_date as reg_date, e.course_id, lv.id as view_id, @@ -24,3 +25,4 @@ ROUND(100.0 * active_users / users_in_cohort, 2) as retention_rate, courses_count::numeric / users_in_cohort as avg_courses_per_user, avg_time_to_first_view from CTE +; \ No newline at end of file