Files
homework/dmedvedev/11.6 Pet project Conversion_funnel.sql
T
Dmitry Medvedev 2dc158dd95 fixed mistakes
2026-07-19 20:14:03 +05:00

156 lines
4.7 KiB
SQL

CREATE MATERIALIZED
VIEW conversion_funnel AS
-- CTE какое кол-во человек записалось на курс
WITH
enrolled_users
AS
(
SELECT
course_id,
user_id,
COUNT(*) OVER (PARTITION BY course_id) AS enrolled_count
FROM pet_enrollments pe
),
-- СТЕ на начавших смотреть курс
started_users
AS
(
SELECT
eu.course_id,
COUNT(DISTINCT plv.user_id) AS started
FROM enrolled_users eu -- Базой берем записанных пользователей
LEFT JOIN pet_lessons pl
ON eu.course_id = pl.course_id
LEFT JOIN pet_lesson_views plv
ON plv.lesson_id = pl.id AND plv.user_id = eu.user_id
-- Проверяем, что смотрел именно записанный юзер
GROUP BY eu.course_id
),
--СТЕ на кол-во просмотров курса и прогресс по курсу
user_progress
AS
(
SELECT
eu.course_id,
eu.user_id,
COUNT(DISTINCT plv.lesson_id) * 1.0 / count_lesson_in_course.count_lesson_in_course AS progress
FROM enrolled_users eu -- Базой берем записанных пользователей
LEFT JOIN pet_lessons pl
ON pl.course_id = eu.course_id
LEFT JOIN pet_lesson_views plv
ON plv.lesson_id = pl.id AND plv.user_id = eu.user_id -- Просмотры могут быть NULL, если записался, но не смотрел
LEFT JOIN (
SELECT
pl.course_id,
COUNT(*) AS count_lesson_in_course
FROM pet_lessons pl
GROUP BY pl.course_id
) AS count_lesson_in_course
ON count_lesson_in_course.course_id = eu.course_id
GROUP BY eu.course_id, eu.user_id, count_lesson_in_course.count_lesson_in_course
),
main_table
AS
(
SELECT
pc.id AS course_id,
pc.title AS course_title,
'registered' AS stage_name,
0 AS stage_order,
(SELECT COUNT(*)
FROM pet_users pu) AS users_count,
ROUND(100, 2) || '%' AS conversion_from_previous,
ROUND(100, 2) || '%' AS conversion_from_start
FROM pet_courses pc
UNION ALL
SELECT
pc.id AS course_id,
pc.title AS course_title,
'enrolled' AS stage_name,
1 AS stage_order,
COALESCE(eu.enrolled_count, 0),
ROUND(COALESCE(eu.enrolled_count, 0) * 100.0 / NULLIF((SELECT COUNT(*) FROM pet_users), 0), 2) || '%' AS conversion_from_previous,
ROUND(COALESCE(eu.enrolled_count, 0) * 100.0 / NULLIF((SELECT COUNT(*) FROM pet_users), 0), 2) || '%' AS conversion_from_start
FROM pet_courses pc
LEFT JOIN (SELECT course_id, MAX(enrolled_count) AS enrolled_count
FROM enrolled_users
GROUP BY course_id) eu
ON eu.course_id = pc.id
UNION ALL
SELECT
pc.id AS course_id,
pc.title AS course_title,
'started' AS stage_name,
2 AS stage_order,
COALESCE(su.started, 0),
ROUND(COALESCE(su.started, 0) * 100.0 / NULLIF(eu.enrolled_count, 0), 2) || '%' AS conversion_from_previous,
ROUND(COALESCE(su.started, 0) * 100.0 / NULLIF((SELECT COUNT(*) FROM pet_users), 0), 2) || '%' AS conversion_from_start
FROM pet_courses pc
LEFT JOIN (SELECT course_id, MAX(enrolled_count) AS enrolled_count
FROM enrolled_users
GROUP BY course_id) eu
ON eu.course_id = pc.id
LEFT JOIN started_users su
ON su.course_id = pc.id
UNION ALL
SELECT
pc.id AS course_id,
pc.title AS course_title,
'mid_progress' AS stage_name,
3 AS stage_order,
(SELECT COUNT(*)
FROM user_progress up
WHERE up.course_id = pc.id AND up.progress >= 0.5),
ROUND((SELECT COUNT(*)
FROM user_progress up
WHERE up.course_id = pc.id AND up.progress >= 0.5) * 100.0 / NULLIF(su.started, 0), 2) || '%' AS conversion_from_previous,
ROUND((SELECT COUNT(*)
FROM user_progress up
WHERE up.course_id = pc.id AND up.progress >= 0.5) * 100.0 / NULLIF((SELECT COUNT(*) FROM pet_users), 0), 2) || '%' AS conversion_from_start
FROM pet_courses pc
LEFT JOIN started_users su
ON su.course_id = pc.id
UNION ALL
SELECT
pc.id AS course_id,
pc.title AS course_title,
'completed' AS stage_name,
4 AS stage_order,
(SELECT COUNT(*)
FROM user_progress up
WHERE up.course_id = pc.id AND up.progress >= 1),
ROUND((SELECT COUNT(*)
FROM user_progress up
WHERE up.course_id = pc.id AND up.progress >= 1) * 100.0 / NULLIF((SELECT COUNT(*) FROM user_progress up WHERE up.course_id = pc.id AND up.progress >= 0.5), 0), 2) || '%' AS conversion_from_previous,
ROUND((SELECT COUNT(*)
FROM user_progress up
WHERE up.course_id = pc.id AND up.progress >= 1) * 100.0 / NULLIF((SELECT COUNT(*) FROM pet_users), 0), 2) || '%' AS conversion_from_start
FROM pet_courses pc
)
-- main select
SELECT
course_id,
course_title,
stage_name,
users_count,
conversion_from_previous,
conversion_from_start
FROM main_table
ORDER BY course_id, stage_order;