DROP MATERIALIZED VIEW IF EXISTS dmezentsev.conversion_funnel; CREATE MATERIALIZED VIEW dmezentsev.conversion_funnel AS WITH progress AS ( -- Прогресс каждого пользователя по каждому курсу SELECT e.course_id, e.user_id, COUNT(DISTINCT l.id) AS total_lessons, COUNT(DISTINCT lv.lesson_id) AS viewed_lessons, ROUND(COUNT(DISTINCT lv.lesson_id) * 100.0 / NULLIF(COUNT(DISTINCT l.id), 0), 2) AS viewed_pct FROM dmezentsev.enrollments e LEFT JOIN dmezentsev.lessons l ON e.course_id = l.course_id LEFT JOIN dmezentsev.lesson_views lv ON l.id = lv.lesson_id AND e.user_id = lv.user_id GROUP BY e.course_id, e.user_id ), funnel_stats AS ( -- Статистика по каждому курсу для всех этапов воронки SELECT c.id AS course_id, c.title AS course_title, (SELECT COUNT(*) FROM dmezentsev.users_) AS registered_count, COUNT(DISTINCT e.user_id) AS enrolled_count, COUNT(DISTINCT CASE WHEN p.viewed_lessons > 0 THEN e.user_id END) AS started_count, COUNT(DISTINCT CASE WHEN p.viewed_pct >= 50 THEN e.user_id END) AS mid_progress_count, COUNT(DISTINCT CASE WHEN p.viewed_pct = 100 THEN e.user_id END) AS completed_count FROM dmezentsev.courses c LEFT JOIN dmezentsev.enrollments e ON c.id = e.course_id LEFT JOIN progress p ON e.course_id = p.course_id AND e.user_id = p.user_id GROUP BY c.id, c.title ) -- Соединяем этапы с помощью UNION ALL SELECT course_id, course_title, stage_name, users_count, conversion_from_previous, conversion_from_start FROM ( -- Этап 1: registered SELECT course_id, course_title, 'registered' AS stage_name, registered_count AS users_count, 0 AS conversion_from_previous, 100.00 AS conversion_from_start, 1 AS stage_order FROM funnel_stats UNION ALL -- Этап 2: enrolled SELECT course_id, course_title, 'enrolled', enrolled_count, ROUND(100.0 * enrolled_count / NULLIF(registered_count, 0), 2), ROUND(100.0 * enrolled_count / NULLIF(registered_count, 0), 2), 2 AS stage_order FROM funnel_stats UNION ALL -- Этап 3: started SELECT course_id, course_title, 'started', started_count, ROUND(100.0 * started_count / NULLIF(enrolled_count, 0), 2), ROUND(100.0 * started_count / NULLIF(registered_count, 0), 2), 3 AS stage_order FROM funnel_stats UNION ALL -- Этап 4: mid_progress SELECT course_id, course_title, 'mid_progress', mid_progress_count, ROUND(100.0 * mid_progress_count / NULLIF(started_count, 0), 2), ROUND(100.0 * mid_progress_count / NULLIF(registered_count, 0), 2), 4 AS stage_order FROM funnel_stats UNION ALL -- Этап 5: completed SELECT course_id, course_title, 'completed', completed_count, ROUND(100.0 * completed_count / NULLIF(mid_progress_count, 0), 2), ROUND(100.0 * completed_count / NULLIF(registered_count, 0), 2), 5 AS stage_order FROM funnel_stats ) AS funnel_rows ORDER BY course_id, stage_order;