Merge pull request 'OS-330' (#45) from OS-330 into main
Reviewed-on: https://gitea.de-infra.servehttp.com/de-infrastructure/DWH/pulls/45
This commit is contained in:
@@ -0,0 +1,215 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS amaksatov.users (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name VARCHAR(100),
|
||||||
|
age INT,
|
||||||
|
email VARCHAR(255),
|
||||||
|
registration_date DATE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS amaksatov.courses (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
title VARCHAR(255),
|
||||||
|
category VARCHAR(100),
|
||||||
|
created_at DATE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS amaksatov.lessons (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
course_id INT,
|
||||||
|
title VARCHAR(255),
|
||||||
|
duration_min INT,
|
||||||
|
FOREIGN KEY (course_id) REFERENCES amaksatov.courses(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS amaksatov.enrollments (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
user_id INT,
|
||||||
|
course_id INT,
|
||||||
|
enrolled_at date,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES amaksatov.users(id),
|
||||||
|
FOREIGN KEY (course_id) REFERENCES amaksatov.courses(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS amaksatov.lesson_views (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
user_id INT,
|
||||||
|
lesson_id INT,
|
||||||
|
viewed_at TIMESTAMP,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES amaksatov.users(id),
|
||||||
|
FOREIGN KEY (lesson_id) REFERENCES amaksatov.lessons(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
INSERT
|
||||||
|
INTO
|
||||||
|
amaksatov.users (
|
||||||
|
name,
|
||||||
|
age,
|
||||||
|
email,
|
||||||
|
registration_date
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'Alice',
|
||||||
|
25,
|
||||||
|
'alice@mail.com',
|
||||||
|
'2023-01-10'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'Bob',
|
||||||
|
30,
|
||||||
|
'bob@gmail.com',
|
||||||
|
'2023-02-05'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'Charlie',
|
||||||
|
22,
|
||||||
|
'charlie@mail.com',
|
||||||
|
'2023-02-20'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'Diana',
|
||||||
|
28,
|
||||||
|
'diana@mail.com',
|
||||||
|
'2023-03-01'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'Ethan',
|
||||||
|
35,
|
||||||
|
'ethan@gmail.com',
|
||||||
|
'2023-03-10'
|
||||||
|
);
|
||||||
|
|
||||||
|
SELECT * FROM amaksatov.users;
|
||||||
|
|
||||||
|
|
||||||
|
INSERT
|
||||||
|
INTO
|
||||||
|
amaksatov.courses (
|
||||||
|
title,
|
||||||
|
category,
|
||||||
|
created_at
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
(
|
||||||
|
'SQL для начинающих',
|
||||||
|
'data',
|
||||||
|
'2023-01-01'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'Python для анализа данных',
|
||||||
|
'programming',
|
||||||
|
'2023-01-15'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'BI с нуля',
|
||||||
|
'business',
|
||||||
|
'2023-03-01'
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT
|
||||||
|
INTO
|
||||||
|
amaksatov.lessons (
|
||||||
|
course_id,
|
||||||
|
title,
|
||||||
|
duration_min
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
(
|
||||||
|
1,
|
||||||
|
'SELECT и FROM',
|
||||||
|
10
|
||||||
|
),
|
||||||
|
(
|
||||||
|
1,
|
||||||
|
'JOIN',
|
||||||
|
15
|
||||||
|
),
|
||||||
|
(
|
||||||
|
2,
|
||||||
|
'Pandas',
|
||||||
|
20
|
||||||
|
),
|
||||||
|
(
|
||||||
|
3,
|
||||||
|
'Основы BI',
|
||||||
|
12
|
||||||
|
),
|
||||||
|
(
|
||||||
|
3,
|
||||||
|
'Метрики и дашборды',
|
||||||
|
18
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT
|
||||||
|
INTO
|
||||||
|
amaksatov.enrollments (
|
||||||
|
user_id,
|
||||||
|
course_id,
|
||||||
|
enrolled_at
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
(
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
'2023-01-15'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
'2023-02-01'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
'2023-01-20'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
3,
|
||||||
|
2,
|
||||||
|
'2023-03-05'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
4,
|
||||||
|
3,
|
||||||
|
'2023-04-01'
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT
|
||||||
|
INTO
|
||||||
|
amaksatov.lesson_views (
|
||||||
|
user_id,
|
||||||
|
lesson_id,
|
||||||
|
viewed_at
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
(
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
'2023-01-16 10:00:00'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
'2023-01-16 10:15:00'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
'2023-01-21 09:00:00'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
3,
|
||||||
|
3,
|
||||||
|
'2023-03-06 12:00:00'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
4,
|
||||||
|
4,
|
||||||
|
'2023-04-02 10:00:00'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
'2023-04-03 10:00:00'
|
||||||
|
);
|
||||||
|
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
|
||||||
|
CREATE MATERIALIZED VIEW user_activity_summary AS
|
||||||
|
SELECT
|
||||||
|
u.id AS user_id, -- user_id
|
||||||
|
u.name, -- name
|
||||||
|
COUNT(DISTINCT e.course_id) AS enrollment_count, -- кол-во записей на курсы
|
||||||
|
COUNT(DISTINCT lv.lesson_id) AS viewed_lessons_count, -- кол-во просмотренных уроков
|
||||||
|
MAX(lv.viewed_at) AS last_viewed, -- последний просмотр
|
||||||
|
MIN(lv.viewed_at) AS first_viewed, -- первый просмотр
|
||||||
|
ROUND(COUNT(DISTINCT l.course_id) * 100.0 / COUNT(DISTINCT l.id), 2) || '%' AS engagement_rate -- вовлеченность(процент просмотренных/записанным)
|
||||||
|
FROM amaksatov.users u -- основная таблица
|
||||||
|
JOIN enrollments e ON e.user_id = u.id -- связь users с enrollments
|
||||||
|
LEFT JOIN lesson_views lv ON lv.user_id = e.user_id -- связь lessons с lesson_views
|
||||||
|
JOIN lessons l ON l.course_id = e.course_id -- связь уроков с курсами пользователя
|
||||||
|
GROUP BY u.id, u.name -- группировка по user_id и name
|
||||||
|
ORDER BY user_id; -- сортировка по user_id
|
||||||
|
|
||||||
|
|
||||||
|
CREATE MATERIALIZED VIEW course_summary AS
|
||||||
|
SELECT
|
||||||
|
c.id AS course_id,
|
||||||
|
c.title AS course_title,
|
||||||
|
COUNT(DISTINCT e.user_id) AS unique_users,
|
||||||
|
COUNT(DISTINCT l.id) AS lessons_count,
|
||||||
|
COUNT(DISTINCT lv.id) AS total_views,
|
||||||
|
ROUND(
|
||||||
|
CASE
|
||||||
|
WHEN COUNT(DISTINCT e.user_id) = 0 THEN NULL
|
||||||
|
ELSE COUNT(DISTINCT lv.id) * 1.0 / COUNT(DISTINCT e.user_id)
|
||||||
|
END, 2) AS avg_views_per_user,
|
||||||
|
MIN(lv.viewed_at) AS first_viewed_at,
|
||||||
|
MAX(lv.viewed_at) AS last_viewed_at
|
||||||
|
FROM courses c
|
||||||
|
LEFT JOIN enrollments e ON e.course_id = c.id
|
||||||
|
LEFT JOIN lessons l ON c.id = l.course_id
|
||||||
|
LEFT JOIN lesson_views lv ON lv.lesson_id = l.id
|
||||||
|
GROUP BY c.id;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE MATERIALIZED VIEW platform_summary AS
|
||||||
|
WITH
|
||||||
|
user_stats AS (
|
||||||
|
SELECT COUNT(*) AS total_users FROM users
|
||||||
|
),
|
||||||
|
course_stats AS (
|
||||||
|
SELECT COUNT(*) AS total_courses FROM courses
|
||||||
|
),
|
||||||
|
lesson_stats AS (
|
||||||
|
SELECT COUNT(*) AS total_lessons FROM lessons
|
||||||
|
),
|
||||||
|
view_stats AS (
|
||||||
|
SELECT COUNT(*) AS total_views, COUNT(DISTINCT user_id) AS users_with_views
|
||||||
|
FROM lesson_views
|
||||||
|
)
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
u.total_users,
|
||||||
|
c.total_courses,
|
||||||
|
l.total_lessons,
|
||||||
|
v.users_with_views,
|
||||||
|
|
||||||
|
ROUND(l.total_lessons::decimal / NULLIF(c.total_courses, 0), 2) AS avg_lessons_per_course,
|
||||||
|
ROUND(v.total_views::decimal / NULLIF(l.total_lessons, 0), 2) AS avg_views_per_lesson
|
||||||
|
|
||||||
|
FROM user_stats u, course_stats c, lesson_stats l, view_stats v;
|
||||||
Reference in New Issue
Block a user