Files
homework/ebelykh/postgresql/ПЭТ проект/Script.sql
T
2026-01-23 21:49:18 +03:00

233 lines
5.4 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
CREATE TABLE users (
id INT PRIMARY KEY,
name TEXT,
age INT,
email TEXT,
registration_date DATE
);
INSERT INTO users VALUES
(1, 'Alice', 25, 'alice@mail.com', '2023-01-10'),
(2, 'Bob', 30, 'bob@gmail.com', '2023-02-05'),
(3, 'Charlie', 22, 'charlie@mail.com', '2023-02-20'),
(4, 'Diana', 28, 'diana@mail.com', '2023-03-01'),
(5, 'Ethan', 35, 'ethan@gmail.com', '2023-03-10');
SELECT * FROM users ORDER BY id;
CREATE TABLE courses (
id INT PRIMARY KEY,
title TEXT,
category TEXT,
created_at DATE
);
INSERT INTO courses VALUES
(1, 'SQL для начинающих', 'data', '2023-01-01'),
(2, 'Python для анализа данных', 'programming', '2023-01-15'),
(3, 'BI с нуля', 'business', '2023-03-01');
SELECT * FROM courses ORDER BY id;
CREATE TABLE lessons (
id INT PRIMARY KEY,
course_id INT,
title TEXT,
duration_min INT,
FOREIGN KEY (course_id) REFERENCES courses(id)
);
INSERT INTO lessons VALUES
(1, 1, 'SELECT и FROM', 10),
(2, 1, 'JOIN', 15),
(3, 2, 'Pandas', 20),
(4, 3, 'Основы BI', 12),
(5, 3, 'Метрики и дашборды', 18);
SELECT * FROM lessons ORDER BY id;
CREATE TABLE enrollments (
id INT PRIMARY KEY,
user_id INT,
course_id INT,
enrolled_at DATE,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (course_id) REFERENCES courses(id)
);
INSERT INTO enrollments VALUES
(1, 1, 1, '2023-01-15'),
(2, 1, 2, '2023-02-01'),
(3, 2, 1, '2023-01-20'),
(4, 3, 2, '2023-03-05'),
(5, 4, 3, '2023-04-01');
SELECT * FROM enrollments ORDER BY id;
CREATE TABLE lesson_views (
id INT PRIMARY KEY,
user_id INT,
lesson_id INT,
viewed_at TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (lesson_id) REFERENCES lessons(id)
);
INSERT INTO lesson_views VALUES
(1, 1, 1, '2023-01-16 10:00:00'),
(2, 1, 2, '2023-01-16 10:15:00'),
(3, 2, 1, '2023-01-21 09:00:00'),
(4, 3, 3, '2023-03-06 12:00:00'),
(5, 4, 4, '2023-04-02 10:00:00'),
(6, 4, 5, '2023-04-03 10:00:00');
SELECT * FROM lesson_views ORDER BY id;
--Создаем materialized view c названием user_activity_summary
DROP MATERIALIZED VIEW IF EXISTS user_activity_summary;
CREATE MATERIALIZED VIEW user_activity_summary AS
WITH
enr AS (
SELECT
user_id,
COUNT(*) AS enrollment_count
FROM enrollments
GROUP BY user_id
),
views AS (
SELECT
user_id,
COUNT(DISTINCT lesson_id) AS viewed_lessons_count,
MIN(viewed_at) AS first_view,
MAX(viewed_at) AS last_view
FROM lesson_views
GROUP BY user_id
),
possible AS (
SELECT
e.user_id,
COUNT(l.id) AS possible_lessons
FROM enrollments e
JOIN lessons l ON l.course_id = e.course_id
GROUP BY e.user_id
)
SELECT
u.id AS user_id,
u.name,
enr.enrollment_count,
COALESCE(views.viewed_lessons_count, 0) AS viewed_lessons_count,
views.last_view,
views.first_view,
ROUND(
COALESCE(views.viewed_lessons_count, 0)::numeric
/ possible.possible_lessons * 100,
2
) || '%' AS engagement_rate
FROM users u
JOIN enr ON enr.user_id = u.id
JOIN possible ON possible.user_id = u.id
LEFT JOIN views ON views.user_id = u.id
ORDER BY u.id;
--Проверка
SELECT * FROM user_activity_summary ORDER BY user_id;
--Создаем materialized view c названием course_summary
DROP MATERIALIZED VIEW IF EXISTS course_summary;
CREATE MATERIALIZED VIEW course_summary AS
WITH
-- 1) сколько уроков в каждом курсе
lessons_cnt AS (
SELECT
course_id,
COUNT(*) AS lessons_count
FROM lessons
GROUP BY course_id
),
-- 2) сколько уникальных пользователей записано на курс
users_cnt AS (
SELECT
course_id,
COUNT(DISTINCT user_id) AS unique_users
FROM enrollments
GROUP BY course_id
),
-- 3) просмотры по курсу (через lessons -> course_id)
views_cnt 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 lessons l
LEFT JOIN lesson_views lv ON lv.lesson_id = l.id
GROUP BY l.course_id
)
SELECT
c.id AS course_id,
c.title AS course_title,
COALESCE(u.unique_users, 0) AS unique_users,
COALESCE(ls.lessons_count, 0) AS lessons_count,
COALESCE(v.total_views, 0) AS total_views,
ROUND(
COALESCE(v.total_views, 0)::numeric / NULLIF(COALESCE(u.unique_users, 0), 0),
2
) AS avg_views_per_user,
v.first_viewed_at,
v.last_viewed_at
FROM courses c
LEFT JOIN users_cnt u ON u.course_id = c.id
LEFT JOIN lessons_cnt ls ON ls.course_id = c.id
LEFT JOIN views_cnt v ON v.course_id = c.id
ORDER BY c.id;
SELECT * FROM course_summary ORDER BY course_id;
--Создаем materialized view c названием platform_summary
DROP MATERIALIZED VIEW IF EXISTS platform_summary;
CREATE MATERIALIZED VIEW platform_summary AS
SELECT
(SELECT COUNT(*) FROM users) AS total_users,
(SELECT COUNT(*) FROM courses) AS total_courses,
(SELECT COUNT(*) FROM lessons) AS total_lessons,
(SELECT COUNT(DISTINCT user_id) FROM lesson_views) AS users_with_views,
ROUND(
(SELECT COUNT(*) FROM lessons)::numeric
/ (SELECT COUNT(*) FROM courses),
2
) AS avg_lessons_per_course,
ROUND(
(SELECT COUNT(*) FROM lesson_views)::numeric
/ (SELECT COUNT(*) FROM lessons),
2
) AS avg_views_per_lesson;
SELECT * FROM platform_summary;
--Доп. задание: EXPLAIN
EXPLAIN SELECT * FROM user_activity_summary;
EXPLAIN SELECT * FROM course_summary;