Применяем весь курс на практике: от простых SELECT до оконных функций и CTE
| Таблица | Ключевые поля | Описание |
|---|---|---|
| users | id, name, age, gender, city | Пользователи |
| communities | id, name, rating | Сообщества |
| posts | id, community_id, title, score | Публикации |
| likes | id, user_id, post_id, liked_at | Лайки к постам |
| views | id, user_id, community_id, viewed_at | Просмотры сообществ |
Первый блок дашборда — сводные цифры: сколько пользователей, лайков, просмотров и каков средний score постов.
SELECT
(SELECT COUNT(*) FROM users) AS total_users,
(SELECT COUNT(*) FROM communities) AS total_communities,
(SELECT COUNT(*) FROM posts) AS total_posts,
(SELECT COUNT(*) FROM likes) AS total_likes,
(SELECT COUNT(*) FROM views) AS total_views,
(SELECT ROUND(AVG(score), 1) FROM posts) AS avg_score;
| total_users | total_communities | total_posts | total_likes | total_views | avg_score |
|---|---|---|---|---|---|
| 10 | 6 | 13 | 18 | 18 | 853.8 |
Какие публикации вызвали наибольший отклик аудитории? Объединяем posts и likes.
SELECT
p.title,
c.name AS community,
p.score,
COUNT(l.id) AS likes_count
FROM posts p
JOIN communities c ON c.id = p.community_id
LEFT JOIN likes l ON l.post_id = p.id
GROUP BY p.id, p.title, c.name, p.score
ORDER BY likes_count DESC, p.score DESC
LIMIT 5;
| title | community | score | likes_count |
|---|---|---|---|
| review top games 2026 | GamersHub | 950 | 3 |
| guide photo editing basics | PhotoWorld | 780 | 3 |
| tutorial Python basics | TechTalks | 600 | 2 |
| review AI tools for devs | TechTalks | 1100 | 2 |
| analysis esports stats | GamersHub | 870 | 2 |
Самые активные пользователи — те, кто поставил больше всего лайков. Считаем и добавляем их город.
SELECT
u.name,
u.city,
COUNT(l.id) AS likes_count
FROM users u
LEFT JOIN likes l ON l.user_id = u.id
GROUP BY u.id, u.name, u.city
ORDER BY likes_count DESC
LIMIT 5;
| name | city | likes_count |
|---|---|---|
| Andrey | Moscow | 4 |
| Anna | Saint Petersburg | 3 |
| Kate | Novosibirsk | 3 |
| Natalie | Novosibirsk | 2 |
| Dmitriy | Moscow | 2 |
Для каждого сообщества: рейтинг, количество постов, средний score постов, количество лайков и просмотров.
SELECT
c.name,
c.rating,
COUNT(DISTINCT p.id) AS posts_count,
ROUND(AVG(p.score), 1) AS avg_score,
COUNT(DISTINCT l.id) AS likes_count,
COUNT(DISTINCT v.id) AS views_count
FROM communities c
LEFT JOIN posts p ON p.community_id = c.id
LEFT JOIN likes l ON l.post_id = p.id
LEFT JOIN views v ON v.community_id = c.id
GROUP BY c.id, c.name, c.rating
ORDER BY likes_count DESC;
| name | rating | posts_count | avg_score | likes_count | views_count |
|---|---|---|---|---|---|
| TechTalks | 4.6 | 3 | 933.3 | 6 | 7 |
| GamersHub | 4.3 | 3 | 906.7 | 6 | 5 |
| PhotoWorld | 3.8 | 2 | 830.0 | 4 | 3 |
| TravelDiaries | 4.2 | 2 | 825.0 | 1 | 2 |
| FoodLovers | 4.1 | 2 | 700.0 | 1 | 1 |
| SportLife | 3.5 | 1 | 720.0 | 0 | 0 |
«Новый» пользователь — тот, кто поставил первый лайк в данном месяце. Смотрим, как растёт аудитория.
WITH first_like AS (
SELECT
user_id,
MIN(liked_at) AS first_at,
DATE_TRUNC('month', MIN(liked_at))::date AS cohort_month
FROM likes
GROUP BY user_id
)
SELECT
cohort_month,
COUNT(*) AS new_users
FROM first_like
GROUP BY cohort_month
ORDER BY cohort_month;
| cohort_month | new_users |
|---|---|
| 2026-01-01 | 7 |
| 2026-02-01 | 2 |
7 пользователей сделали первый лайк в январе 2026, ещё 2 впервые проявили активность в феврале.
Оконные функции (RANK, DENSE_RANK, ROW_NUMBER) позволяют ранжировать строки внутри групп, не теряя детализацию.
-- Ранг пользователей по лайкам внутри каждого города
SELECT
u.name,
u.city,
COUNT(l.id) AS likes_count,
RANK() OVER (PARTITION BY u.city ORDER BY COUNT(l.id) DESC) AS rnk,
DENSE_RANK() OVER (PARTITION BY u.city ORDER BY COUNT(l.id) DESC) AS dense_rnk
FROM users u
LEFT JOIN likes l ON l.user_id = u.id
GROUP BY u.id, u.name, u.city
ORDER BY u.city, rnk;
| name | city | likes_count | rnk | dense_rnk |
|---|---|---|---|---|
| Elvira | Kazan | 2 | 1 | 1 |
| Andrey | Moscow | 4 | 1 | 1 |
| Dmitriy | Moscow | 2 | 2 | 2 |
| Irina | Moscow | 1 | 3 | 3 |
| Maria | Moscow | 1 | 3 | 3 |
| Kate | Novosibirsk | 3 | 1 | 1 |
| Natalie | Novosibirsk | 2 | 2 | 2 |
| Anna | Saint Petersburg | 3 | 1 | 1 |
-- Накопительный итог лайков по датам
SELECT
liked_at,
COUNT(*) AS daily_likes,
SUM(COUNT(*)) OVER (ORDER BY liked_at) AS cumulative_likes
FROM likes
GROUP BY liked_at
ORDER BY liked_at;
| liked_at | daily_likes | cumulative_likes |
|---|---|---|
| 2026-01-01 | 2 | 2 |
| 2026-01-03 | 1 | 3 |
| 2026-01-07 | 1 | 4 |
| 2026-01-08 | 3 | 7 |
| 2026-01-10 | 2 | 9 |
| 2026-01-12 | 3 | 12 |
| 2026-01-15 | 1 | 13 |
| 2026-01-20 | 2 | 15 |
| 2026-02-05 | 1 | 16 |
| 2026-02-10 | 1 | 17 |
| 2026-02-15 | 1 | 18 |
SUM(COUNT(*)) OVER (ORDER BY liked_at) — оконная функция поверх агрегата. COUNT(*) агрегирует строки в группе, а SUM … OVER считает накопительный итог по всем группам в порядке даты.За эти девять модулей вы освоили:
Следующий шаг — практика на реальных данных. Попробуйте Kaggle, public datasets PostgreSQL или откройте свою базу данных в pgAdmin и задайте ей правильные вопросы.