BEGIN; CREATE MATERIALIZED VIEW user_activity_summary AS WITH users_views AS ( SELECT u.id AS user_id, u.name, COUNT(DISTINCT lv.lesson_id) AS viewed_lessons_count, MAX(lv.viewed_at) AS last_view, MIN(lv.viewed_at) AS first_view FROM users AS u JOIN lesson_views AS lv on u.id = lv.user_id GROUP BY u.id ), users_engagement AS ( SELECT e.user_id AS user_id, COUNT(DISTINCT l.id) AS lessons_cnt, COUNT(DISTINCT course_id) AS enrollment_count FROM enrollments AS e JOIN lessons AS l using(course_id) GROUP BY e.user_id ) SELECT uv.user_id, uv.name, ue.enrollment_count, uv.viewed_lessons_count, uv.last_view, uv.first_view, ROUND(uv.viewed_lessons_count::DECIMAL / NULLIF(ue.lessons_cnt, 0) * 100, 2) AS engagement_rate FROM users_views AS uv LEFT JOIN users_engagement AS ue using (user_id) ORDER BY uv.user_id COMMIT;