CREATE database pet; -- Этап 1 -- Задание 1 -- Перенести данные как в пет-проекте с Greenplum -- Создаем таблицы, чтобы потом загрузить в них данные из таблиц GreenPlum -- Таблица user из GP CREATE TABLE pet.core_user ( user_id Int32, name String, age Int32, email String, registration_date DateTime64(3, 'UTC') ) ENGINE = MergeTree ORDER BY user_id; -- Таблица course из GP CREATE TABLE pet.core_course ( course_id Int32, title String, category String ) ENGINE = MergeTree ORDER BY course_id; -- Таблица lesson из GP CREATE TABLE pet.core_lesson ( lesson_id Int32, title String, duration_min Int32, course_id Int32 ) ENGINE = MergeTree ORDER BY lesson_id; -- Таблица fact_lesson_views из GP CREATE TABLE pet.core_fact_lesson_views ( user_id Int32, lesson_id Int32, course_id Int32, viewed_at DateTime64(3, 'UTC') ) ENGINE = MergeTree ORDER BY user_id; -- Таблица enrollments из GP CREATE TABLE pet.core_enrollments ( user_id Int32, course_id Int32, enrolled_at DateTime64(3, 'UTC') ) ENGINE = MergeTree ORDER BY user_id; -- Этап 2. Создание витринных таблиц -- Задание 2: Подготовь структуру витрины lesson_popularity_summary -- Создаем пустую таблицу lesson_popularity_summary(структуру витрины) CREATE TABLE pet.lesson_popularity_summary ( lesson_id UInt32, lesson_title String, course_id UInt32, course_title String, total_views UInt32, unique_users UInt32, first_view DateTime64(3, 'UTC'), last_view DateTime64(3, 'UTC') ) ENGINE = MergeTree ORDER BY (lesson_id, course_id); -- Создаем Materialized View CREATE MATERIALIZED VIEW pet.mv_lesson_popularity_summary TO pet.lesson_popularity_summary AS SELECT flv.lesson_id AS lesson_id, l.title AS lesson_title, flv.course_id AS course_id, c.title AS course_title, count() AS total_views, uniqExact(flv.user_id) AS unique_users, min(flv.viewed_at) AS first_view, max(flv.viewed_at) AS last_view FROM pet.core_fact_lesson_views AS flv JOIN pet.core_lesson AS l ON flv.lesson_id = l.lesson_id JOIN pet.core_course AS c ON flv.course_id = c.course_id GROUP BY flv.lesson_id, l.title, flv.course_id, c.title; -- Вставляем данные в таблицу pet.lesson_popularity_summary INSERT INTO pet.lesson_popularity_summary SELECT flv.lesson_id, l.title AS lesson_title, flv.course_id, c.title AS course_title, count() AS total_views, uniqExact(flv.user_id) AS unique_users, min(flv.viewed_at) AS first_view, max(flv.viewed_at) AS last_view FROM pet.core_fact_lesson_views AS flv JOIN pet.core_lesson AS l ON flv.lesson_id = l.lesson_id JOIN pet.core_course AS c ON flv.course_id = c.course_id GROUP BY flv.lesson_id, l.title, flv.course_id, c.title; -- Задание 3: Создай витрину inactive_users_summary -- Создаем пустую таблицу inactive_users_summary(структуру витрины) CREATE TABLE pet.inactive_users_summary ( user_id UInt32, name String, email String, age UInt8, registered_courses_count UInt32, registration_date DateTime64(3, 'UTC') ) ENGINE = MergeTree ORDER BY (user_id); -- Создаем Materialized View CREATE MATERIALIZED VIEW pet.mv_inactive_users_summary TO pet.inactive_users_summary AS SELECT u.user_id AS user_id, u.name AS name, u.email AS email, u.age AS age, countDistinct(e.course_id) AS registered_courses_count, u.registration_date AS registration_date FROM pet.core_user AS u LEFT JOIN pet.core_enrollments AS e ON u.user_id = e.user_id WHERE u.user_id NOT IN ( SELECT DISTINCT user_id FROM pet.core_fact_lesson_views ) GROUP BY u.user_id, u.name, u.email, u.age, u.registration_date; -- Вставляем данные в таблицу inactive_users_summary INSERT INTO pet.inactive_users_summary SELECT u.user_id, u.name, u.email, u.age, countDistinct(e.course_id) AS registered_courses_count, u.registration_date FROM pet.core_user AS u LEFT JOIN pet.core_enrollments AS e ON u.user_id = e.user_id WHERE u.user_id NOT IN ( SELECT DISTINCT user_id FROM pet.core_fact_lesson_views ) /* * этот подзапрос WHERE... просто выбрасывает всех, кто хоть раз что‑то посмотрел, * независимо от количества строк и особенностей JOIN’ов. */ GROUP BY u.user_id, u.name, u.email, u.age, u.registration_date; -- Задание 4: Создай витрину course_completion_rate CREATE TABLE pet.course_completion_rate ( user_id UInt32, user_name String, course_id UInt32, course_title String, lessons_in_course UInt32, lessons_viewed UInt32, completion_rate Float32 ) ENGINE = MergeTree ORDER BY (user_id, course_id); -- Создаем Materialized View CREATE MATERIALIZED VIEW pet.mv_course_completion_rate TO pet.course_completion_rate AS SELECT u.user_id AS user_id, u.name AS user_name, c.course_id AS course_id, c.title AS course_title, countDistinct(l.lesson_id) AS lessons_in_course, countDistinct(flv.lesson_id) AS lessons_viewed, if(countDistinct(l.lesson_id) = 0,0, round(countDistinct(flv.lesson_id) * 1.0 / countDistinct(l.lesson_id),2) ) AS completion_rate FROM pet.core_enrollments AS e JOIN pet.core_user AS u ON e.user_id = u.user_id JOIN pet.core_course AS c ON e.course_id = c.course_id JOIN pet.core_lesson AS l ON c.course_id = l.course_id LEFT JOIN pet.core_fact_lesson_views AS flv ON flv.user_id = e.user_id AND flv.course_id = e.course_id GROUP BY u.user_id, u.name, c.course_id, c.title; -- Вставляем данные в таблицу pet.course_completion_rate INSERT INTO pet.course_completion_rate -- Создаем две временные таблицы: -- 1) Сколько уроков в каждом курсе WITH lessons_per_course AS ( SELECT course_id, countDistinct(lesson_id) AS lessons_in_course FROM pet.core_lesson GROUP BY course_id ), -- 2) Сколько уроков каждого курса посмотрел пользователь views_per_user_course AS ( SELECT user_id, course_id, countDistinct(lesson_id) AS lessons_viewed FROM pet.core_fact_lesson_views GROUP BY user_id, course_id ) -- Основной запрос SELECT u.user_id, u.name AS user_name, c.course_id, c.title AS course_title, lpc.lessons_in_course, coalesce(vpc.lessons_viewed, 0) AS lessons_viewed, ROUND( COALESCE( NULLIF(coalesce(vpc.lessons_viewed, 0) * 1.0, 0) / NULLIF(lpc.lessons_in_course * 1.0, 0), 0 ), 2 ) AS completion_rate FROM pet.core_user AS u JOIN pet.core_enrollments AS e ON u.user_id = e.user_id JOIN pet.core_course AS c ON e.course_id = c.course_id JOIN lessons_per_course AS lpc ON c.course_id = lpc.course_id LEFT JOIN views_per_user_course AS vpc ON vpc.user_id = u.user_id AND vpc.course_id = c.course_id ORDER BY u.user_id, c.course_id;