убрал : из папок

This commit is contained in:
mnoskov
2026-05-28 18:00:56 +03:00
parent e0b74cdc13
commit f045be8a39
30 changed files with 0 additions and 0 deletions
@@ -0,0 +1,40 @@
CREATE MATERIALIZED VIEW user_cohort_analysis AS
WITH users_and_enrollments_results AS (
SELECT
date_trunc('month', u.registration_date)::date AS cohort_month,
count(DISTINCT u.id) AS users_in_cohort,
count(DISTINCT e.user_id) AS enrolled_users,
count(DISTINCT e.course_id) courses_in_cohort
FROM
users u
JOIN
enrollments e ON u.id = e.user_id
GROUP BY
cohort_month
),
lesson_views_results AS (
SELECT
date_trunc('month', u.registration_date)::date AS cohort_month,
count(DISTINCT lv.user_id) AS active_users,
round(avg(lv.viewed_at::date - u.registration_date::date), 0) AS avg_time_to_first_view
FROM
users u
LEFT JOIN
lesson_views lv ON u.id = lv.user_id
GROUP BY
cohort_month
)
SELECT
uer.cohort_month,
uer.users_in_cohort,
uer.enrolled_users,
lvr.active_users,
round((lvr.active_users / uer.users_in_cohort::numeric) * 100, 2) || '%' AS retention_rate,
round(uer.courses_in_cohort / uer.users_in_cohort::numeric, 2) AS avg_courses_per_user,
lvr.avg_time_to_first_view
FROM
users_and_enrollments_results uer
JOIN
lesson_views_results lvr ON uer.cohort_month = lvr.cohort_month
ORDER BY
uer.cohort_month;
@@ -0,0 +1,114 @@
CREATE MATERIALIZED VIEW conversion_funnel AS
WITH stage_courses AS (
-- registered
(SELECT
0 AS course_id,
1 AS stage_id,
'registered' AS stage_name,
count(DISTINCT u.id) AS users_count
FROM
users u)
UNION ALL
-- enrolled
(SELECT
e.course_id,
2 AS stage_id,
'enrolled' AS stage_name,
count(DISTINCT e.user_id) AS users_count
FROM
enrollments e
GROUP BY
e.course_id
ORDER BY
e.course_id)
UNION ALL
-- started
(SELECT
l.course_id,
3 AS stage_id,
'started' AS stage_name,
count(DISTINCT lv.user_id) AS users_count
FROM
lessons l
JOIN
lesson_views lv ON l.id = lv.lesson_id
GROUP BY
l.course_id
ORDER BY
l.course_id)
UNION ALL
-- mid_progress
(WITH lessons_mid AS (
SELECT
l.course_id,
ceil(percentile_cont(0.5) WITHIN GROUP (ORDER BY l.id)) AS mid_in_lesson_id
FROM
lessons l
GROUP BY
l.course_id
)
SELECT
lm.course_id,
4 AS stage_id,
'mid_progress' AS stage_name,
count(lv.user_id) AS users_count
FROM
lessons_mid lm
LEFT JOIN
lesson_views lv ON lm.mid_in_lesson_id = lv.lesson_id
GROUP BY
lm.course_id, lm.mid_in_lesson_id
ORDER BY
lm.course_id)
UNION ALL
-- completed
(WITH courses_lessons_id AS (
SELECT
l.course_id,
l.id AS lesson_id
FROM
lessons l
GROUP BY
l.course_id, l.id
),
lessons_numbers AS (
SELECT
cli.course_id,
cli.lesson_id,
ROW_NUMBER() OVER(PARTITION BY cli.course_id ORDER BY cli.lesson_id DESC) AS lesson_number
FROM
courses_lessons_id cli
)
SELECT
ln.course_id,
5 AS stage_id,
'completed' AS stage_name,
count(lv.user_id) AS users_count
FROM
lessons_numbers ln
LEFT JOIN
lesson_views lv ON ln.lesson_id = lv.lesson_id
WHERE
ln.lesson_number = 1
GROUP BY
ln.course_id, ln.lesson_id
ORDER BY
ln.course_id)
)
SELECT
sc.course_id,
c.title AS course_title,
sc.stage_name,
sc.users_count,
CASE
WHEN lag(sc.users_count) OVER (PARTITION BY sc.course_id ORDER BY sc.stage_id) IS NULL THEN 'first stage'
WHEN lag(sc.users_count) OVER (PARTITION BY sc.course_id ORDER BY sc.stage_id) = 0 THEN 0::text || '%'
WHEN lag(sc.users_count) OVER (PARTITION BY sc.course_id ORDER BY sc.stage_id) IS NOT NULL THEN round((sc.users_count / lag(sc.users_count) OVER (PARTITION BY sc.course_id ORDER BY sc.stage_id)::NUMERIC) * 100, 0)::text || '%'
END AS conversion_from_previous,
round((sc.users_count / FIRST_VALUE(sc.users_count) OVER (ORDER BY sc.stage_id)::NUMERIC) * 100, 0)::text || '%' AS conversion_from_start
FROM
courses c
RIGHT JOIN
stage_courses sc ON c.id = sc.course_id
ORDER BY
sc.course_id;
@@ -0,0 +1,41 @@
CREATE MATERIALIZED VIEW course_summary AS
WITH courses_unique_users AS (
SELECT
e.course_id,
count(e.user_id) AS unique_users
FROM
enrollments e
GROUP BY
e.course_id
),
lessons_results AS (
SELECT
l.course_id,
count(distinct l.id) AS lessons_count,
count(lv.lesson_id) AS total_views,
min(lv.viewed_at)::date AS first_viewed_at,
max(lv.viewed_at)::date AS last_viewed_at
FROM
lessons l
LEFT JOIN
lesson_views lv ON l.id = lv.lesson_id
GROUP BY
l.course_id
)
SELECT
c.id AS course_id,
c.title AS course_title,
cuu.unique_users,
lr.lessons_count,
lr.total_views,
round(lr.total_views / cuu.unique_users::numeric, 2) AS avg_views_per_user,
lr.first_viewed_at,
lr.last_viewed_at
FROM
courses c
JOIN
courses_unique_users cuu ON c.id = cuu.course_id
JOIN
lessons_results lr ON c.id = lr.course_id
ORDER BY
c.id;
@@ -0,0 +1,39 @@
CREATE MATERIALIZED VIEW lesson_popularity_ranking as
WITH lesson_views_results AS (
SELECT
lv.lesson_id,
count(lv.user_id) AS total_views,
count(DISTINCT lv.user_id) AS unique_viewers
FROM
lesson_views lv
GROUP BY
lv.lesson_id
),
enrollments_results AS (
SELECT
e.course_id,
count(e.user_id) AS enrolled_to_course
FROM
enrollments e
GROUP BY
e.course_id
)
SELECT
l.id AS lesson_id,
l.title AS lesson_title,
c.title AS course_title,
lvr.total_views,
lvr.unique_viewers,
round(lvr.total_views / lvr.unique_viewers::numeric, 2) AS avg_views_per_viewer,
dense_rank() OVER (ORDER BY lvr.total_views desc) AS popularity_rank,
round((lvr.unique_viewers / er.enrolled_to_course::numeric) * 100, 0) || '%' AS completion_rate
FROM
lessons l
JOIN
courses c ON l.course_id = c.id
JOIN
lesson_views_results lvr ON l.id = lvr.lesson_id
JOIN
enrollments_results er ON c.id = er.course_id
ORDER BY
popularity_rank;
@@ -0,0 +1,48 @@
CREATE MATERIALIZED VIEW platform_summary as
WITH users_count AS (
SELECT
count(*) AS total_users
FROM
users
),
courses_count AS (
SELECT
count(*) AS total_courses
FROM
courses
),
lessons_count AS (
SELECT
count(*) AS total_lessons
FROM
lessons
),
users_with_views AS (
SELECT
count(distinct user_id) AS users_with_views
FROM
lesson_views
),
views_count AS (
SELECT
count(*) AS total_views
FROM
lesson_views lv
)
SELECT
uc.total_users,
cc.total_courses,
lc.total_lessons,
uwv.users_with_views,
round(lc.total_lessons / cc.total_courses::NUMERIC, 2) AS avg_lessons_per_course,
round(vc.total_views / lc.total_lessons::NUMERIC, 2) AS avg_views_per_lesson
FROM
users_count uc
CROSS JOIN
courses_count cc
CROSS JOIN
lessons_count lc
CROSS JOIN
users_with_views uwv
CROSS JOIN
views_count AS vc;
@@ -0,0 +1,24 @@
CREATE MATERIALIZED VIEW user_activity_summary AS
SELECT
u.id AS user_id,
u.name,
count(DISTINCT e.course_id) AS enrollment_count,
count(DISTINCT lv.lesson_id) AS viewed_lessons_count,
max(lv.viewed_at)::date AS last_view,
min(lv.viewed_at)::date AS first_view,
((count(DISTINCT lv.lesson_id)::numeric(5,2) / count(DISTINCT l.id)) * 100)::numeric(5, 2) AS engagement_rate
FROM
users u
JOIN
enrollments e ON u.id = e.user_id
JOIN
courses c ON e.course_id = c.id
JOIN
lessons l ON c.id = l.course_id
LEFT JOIN
lesson_views lv ON u.id = lv.user_id -- сюда - 'AND l.id = lv.lesson_id'
GROUP BY
u.id, u.name
ORDER BY
u.id;
-- Кинул его в нейронку на проверку, она сказала что надо добавить 'AND l.id = lv.lesson_id' при присоединении таблицы lesson_views(сделал пометку в коде), это нужно чтобы точно проверить, что урок который посмотрел пользователь точно принадлежит его курсу, чтобы избежать ошибок из-за некорректных данные если такие появятся в результате какого либо сбоя или ошибки.