-- Этап 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;