From 3fc5535e1de060011a92f8d0e64ffada13b32eb4 Mon Sep 17 00:00:00 2001 From: George Date: Thu, 11 Dec 2025 17:59:31 +0300 Subject: [PATCH 1/5] =?UTF-8?q?=D0=9D=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=BB?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=B4=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B8=20=D0=BD=D0=B0=D0=BF=D0=BE=D0=BB=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D0=B5=D1=82-=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BA=D1=82=D0=B0=20=D0=BF=D0=BE=20sql?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gmokrousov/postgresql/creating_tables.sql | 69 +++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 gmokrousov/postgresql/creating_tables.sql diff --git a/gmokrousov/postgresql/creating_tables.sql b/gmokrousov/postgresql/creating_tables.sql new file mode 100644 index 0000000..cc3c095 --- /dev/null +++ b/gmokrousov/postgresql/creating_tables.sql @@ -0,0 +1,69 @@ +create table users ( + id serial primary key, + name varchar(50) not null, + age int not null, + email varchar(100) not null, + registration_date date not null +); + +insert into users (name, age, email, registration_date) values + ('Alice', 25, 'alice@mail.com', ; '2023-01-10'), + ('Bob', 30, 'bob@gmail.com', '2023-02-05'), + ('Charlie', 22, 'Charlie@mail.com', '2023-02-20'), + ('Diana', 28, 'diana@mail.com', '2023-03-01'), + ('Ethan', 35, 'ethan@gmail.com', '2023-03-10'); + +create table courses ( + id serial primary key, + title varchar(100) not null, + category varchar(30) not null, + created_at date not_null +); + +insert into courses (title, category, created_at) values + ('SQL для начинающих', 'data', '2023-01-01'), + ('Python для анализа данных', 'programming', '2023-01-15'), + ('BI с нуля', 'business', '2023-03-01'); + +create table lessons ( + id serial primary key, + course_id int references courses(id), + title varchar(100) not null, + duration_min int not null +); + +insert into lessons (course_id, title, duration_min) values + (1, 'SELECT и FROM', 10), + (1, 'JOIN', 15), + (2, 'Pandas', 20), + (3, 'Основы BI', 12), + (3, 'Метрики и дашборды', 18); + +create table enrollments ( + id serial primary key, + user_id int references users(id), + course_id int references courses(id), + enrolled_at date not null +); + +insert into enrollments (user_id, course_id, enrolled_at) values + (1, 1, '2023-01-15'), + (1, 2, '2023-02-01'), + (2, 1, '2023-01-20'), + (3, 2, '2023-03-05'), + (4, 3, '2023-04-01'); + +create table lesson_views ( + id serial primary key, + user_id int references users(id), + lesson_id int references lessons(id), + viewed_at timestamp(0) not null +); + +insert into lesson_views (user_id, lesson_id, viewed_at) values + (1, 1, '2023-01-16 10:00:00'), + (1, 2, '2023-01-16 10:15:00'), + (2, 1, '2023-01-21 09:00:00'), + (3, 3, '2023-03-06 12:00:00'), + (4, 4, '2023-04-02 10:00:00'), + (4, 5, '2023-04-03 10:00:00'); From 811294366357e2498bef28854360244c33afb2a9 Mon Sep 17 00:00:00 2001 From: George Date: Thu, 11 Dec 2025 18:25:21 +0300 Subject: [PATCH 2/5] =?UTF-8?q?=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0=D0=BB=20?= =?UTF-8?q?=D0=B2=D0=B8=D1=82=D1=80=D0=B8=D0=BD=D1=83=20=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=B8=D0=B2=D0=BD=D0=BE=D1=81=D1=82=D0=B8=20=D1=8E=D0=B7=D0=B5?= =?UTF-8?q?=D1=80=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../postgresql/DM_user_activity_summary.sql | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 gmokrousov/postgresql/DM_user_activity_summary.sql diff --git a/gmokrousov/postgresql/DM_user_activity_summary.sql b/gmokrousov/postgresql/DM_user_activity_summary.sql new file mode 100644 index 0000000..3fb3d94 --- /dev/null +++ b/gmokrousov/postgresql/DM_user_activity_summary.sql @@ -0,0 +1,35 @@ +-- Витрина активности пользователей +CREATE MATERIALIZED VIEW user_activity_summary as + with + lessons_cte as ( + select + user_id, + count (*) as viewed_lessons_count, + max(viewed_at) as last_view, + min(viewed_at) as first_view + from lesson_views + group by user_id + ), + enrollments_cte as ( + select user_id, count(*) as enrollment_count + from enrollments as e + group by user_id + ), + engagement_cte as ( + select user_id, count(*) as possible_lessons + from lessons as l + join enrollments as en on l.course_id = en.course_id + group by user_id + ) + select + id as user_id, + name, + e.enrollment_count, + l.viewed_lessons_count, + l.last_view, + l.first_view, + round(l.viewed_lessons_count::decimal * 100 / en.possible_lessons, 2) as engagement_rate + from users as u + join lessons_cte as l on u.id = l.user_id + join engagement_cte as en on u.id = en.user_id + join enrollments_cte as e on u.id = e.user_id; \ No newline at end of file From ba40e725ba875ab20d23da4a59096cd62ae3ed2c Mon Sep 17 00:00:00 2001 From: George Date: Thu, 11 Dec 2025 18:28:48 +0300 Subject: [PATCH 3/5] =?UTF-8?q?=D0=9D=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=BB?= =?UTF-8?q?=20=D0=B2=D0=B8=D1=82=D1=80=D0=B8=D0=BD=D1=83=20=D0=BF=D0=BE=20?= =?UTF-8?q?=D0=BA=D1=83=D1=80=D1=81=D0=B0=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gmokrousov/postgresql/DM_course_summary.sql | 24 +++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 gmokrousov/postgresql/DM_course_summary.sql diff --git a/gmokrousov/postgresql/DM_course_summary.sql b/gmokrousov/postgresql/DM_course_summary.sql new file mode 100644 index 0000000..e303798 --- /dev/null +++ b/gmokrousov/postgresql/DM_course_summary.sql @@ -0,0 +1,24 @@ +CREATE MATERIALIZED VIEW course_summary as + with + lw as ( + select + user_id, + lesson_id, + viewed_at + from lesson_views + ) + select + id as course_id, + title as course_title, + count(distinct e.user_id) as unique_users, + count(distinct l.lesson_id) as lessons_count, + count(distinct lw.viewed_at) as total_views, + round(count(distinct lw.viewed_at)::decimal / count(distinct e.user_id), 2) as avg_views_per_user, + min(lw.viewed_at) as first_viewed_at, + max(lw.viewed_at) as last_viewed_at + from + courses as c + join (select course_id, user_id from enrollments) as e on c.id = e.course_id + join (select id as lesson_id, course_id from lessons) as l on c.id = l.course_id + join lw on l.lesson_id = lw.lesson_id + group by id; \ No newline at end of file From 717f705fadd10dd2e31dca652e37cc01cb24f8d4 Mon Sep 17 00:00:00 2001 From: George Date: Thu, 11 Dec 2025 18:30:49 +0300 Subject: [PATCH 4/5] =?UTF-8?q?=D0=9D=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=BB?= =?UTF-8?q?=20=D0=B2=D0=B8=D1=82=D1=80=D0=B8=D0=BD=D1=83=20=D1=81=20=D0=BE?= =?UTF-8?q?=D0=B1=D1=89=D0=B5=D0=B9=20=D0=BE=D1=82=D1=87=D1=91=D1=82=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gmokrousov/postgresql/DM_platform_summary.sql | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 gmokrousov/postgresql/DM_platform_summary.sql diff --git a/gmokrousov/postgresql/DM_platform_summary.sql b/gmokrousov/postgresql/DM_platform_summary.sql new file mode 100644 index 0000000..3ff7377 --- /dev/null +++ b/gmokrousov/postgresql/DM_platform_summary.sql @@ -0,0 +1,24 @@ +create materialized view platform_summary as + with + lv_stats as ( + select + count(distinct user_id) as users_with_views, + count(*)::decimal / count(distinct lesson_id) as avg_views_per_lesson + from lesson_views + ) + select + total_users, + total_courses, + total_lessons, + users_with_views, + round((total_lessons::decimal / total_courses), 2) AS avg_lessons_per_course, + round(avg_views_per_lesson, 2) as avg_views_per_lesson + from + ( + select + (select count(*) from users) as total_users, + (select count(*) from courses) as total_courses, + count(*) as total_lessons + from lessons + ) as s + cross join lv_stats as lv; \ No newline at end of file From aaef8066304218d3e39d1e1e72dd832e46032de5 Mon Sep 17 00:00:00 2001 From: George Date: Sat, 13 Dec 2025 22:06:10 +0300 Subject: [PATCH 5/5] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D1=83=20=D0=BD?= =?UTF-8?q?=D0=B0=20null=20=D0=B2=20=D0=B4=D0=B2=D0=B5=20=D0=B4=D0=B0?= =?UTF-8?q?=D1=82=D0=B0=D0=BC=D0=B0=D1=80=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gmokrousov/postgresql/DM_platform_summary.sql | 4 ++-- gmokrousov/postgresql/DM_user_activity_summary.sql | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gmokrousov/postgresql/DM_platform_summary.sql b/gmokrousov/postgresql/DM_platform_summary.sql index 3ff7377..b1ca532 100644 --- a/gmokrousov/postgresql/DM_platform_summary.sql +++ b/gmokrousov/postgresql/DM_platform_summary.sql @@ -3,7 +3,7 @@ create materialized view platform_summary as lv_stats as ( select count(distinct user_id) as users_with_views, - count(*)::decimal / count(distinct lesson_id) as avg_views_per_lesson + count(*)::decimal / nullif(count(distinct lesson_id), as avg_views_per_lesson from lesson_views ) select @@ -11,7 +11,7 @@ create materialized view platform_summary as total_courses, total_lessons, users_with_views, - round((total_lessons::decimal / total_courses), 2) AS avg_lessons_per_course, + round((total_lessons::decimal / nullif(total_courses, 2)), 2) AS avg_lessons_per_course, round(avg_views_per_lesson, 2) as avg_views_per_lesson from ( diff --git a/gmokrousov/postgresql/DM_user_activity_summary.sql b/gmokrousov/postgresql/DM_user_activity_summary.sql index 3fb3d94..c7bc776 100644 --- a/gmokrousov/postgresql/DM_user_activity_summary.sql +++ b/gmokrousov/postgresql/DM_user_activity_summary.sql @@ -28,7 +28,7 @@ CREATE MATERIALIZED VIEW user_activity_summary as l.viewed_lessons_count, l.last_view, l.first_view, - round(l.viewed_lessons_count::decimal * 100 / en.possible_lessons, 2) as engagement_rate + round(l.viewed_lessons_count::decimal * 100 / nullif(en.possible_lessons, 0), 2) as engagement_rate from users as u join lessons_cte as l on u.id = l.user_id join engagement_cte as en on u.id = en.user_id