DROP MATERIALIZED VIEW IF EXISTS dmezentsev.course_summary; CREATE MATERIALIZED VIEW dmezentsev.course_summary AS WITH count_users AS ( -- Кол-во уникальных пользователей в курсах SELECT c.id AS course_id, c.title AS course_title, COUNT(DISTINCT e.user_id) AS unique_users FROM dmezentsev.courses c LEFT JOIN dmezentsev.enrollments e ON c.id = e.course_id GROUP BY c.id, c.title ), count_lessons AS ( -- Кол-во уроков в курсах SELECT course_id, COUNT(id) AS lessons_count FROM dmezentsev.lessons GROUP BY course_id ), views_count AS ( -- Суммарное число просмотров по каждому курсу 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 dmezentsev.lessons l LEFT JOIN dmezentsev.lesson_views lv ON l.id = lv.lesson_id GROUP BY l.course_id ) SELECT cu.course_id, cu.course_title, cu.unique_users, cl.lessons_count, vc.total_views, ROUND(COALESCE(vc.total_views::numeric / cu.unique_users, 0), 2) AS avg_views_per_user, vc.first_viewed_at, vc.last_viewed_at FROM count_users cu LEFT JOIN count_lessons cl USING (course_id) LEFT JOIN views_count vc USING (course_id) ORDER BY cu.course_id;