В прошлом уроке запрос со сборкой JSON по авторам вышел длинным, а в уроке про агрегаты мы писали отчёты о выручке, где каждый раз повторялись одни и те же три JOIN и условие на отменённые заказы. Сегодня учим базу запоминать такие запросы под именем. Примеры работают на учебной базе магазина.
Окно в стене
В квартире есть окно на улицу. Улица в окне не хранится: каждый раз, когда ты в него смотришь, видишь то, что происходит прямо сейчас. Зато окно всегда на одном месте, и не нужно каждый раз выходить на балкон.
Представление, по-английски view, устроено так же. Это запрос, который база хранит под именем. Обращаешься к нему как к таблице, а PostgreSQL каждый раз выполняет запрос заново на свежих данных. Своих данных у представления нет.
Первое представление
Выручка по книгам без отменённых заказов. Раньше мы писали этот запрос целиком, теперь сохраним:
CREATE VIEW book_sales AS
SELECT b.id, b.title,
sum(oi.qty) AS sold,
sum(oi.qty * oi.price) AS revenue
FROM order_items oi
JOIN orders o ON o.id = oi.order_id
JOIN books b ON b.id = oi.book_id
WHERE o.status <> 'cancelled'
GROUP BY b.id, b.title;
Дальше это обычное имя в FROM:
SELECT * FROM book_sales ORDER BY revenue DESC;
id | title | sold | revenue
----+--------------------+------+---------
8 | Совершенный код | 1 | 2490.00
1 | Мастер и Маргарита | 2 | 1380.00
7 | Грокаем алгоритмы | 1 | 1290.00
3 | Пикник на обочине | 2 | 900.00
4 | Трудно быть богом | 1 | 520.00
5 | Шинель | 1 | 250.00
(6 rows)
С представлением работают все приёмы прошлых уроков: WHERE, ORDER BY, JOIN с другими таблицами. Запрос «книги с выручкой больше тысячи» теперь умещается в строку:
SELECT title, revenue FROM book_sales WHERE revenue > 1000 ORDER BY revenue DESC;
title | revenue
--------------------+---------
Совершенный код | 2490.00
Мастер и Маргарита | 1380.00
Грокаем алгоритмы | 1290.00
(3 rows)
Окно всегда свежее
Проверим, что представление ничего не хранит. Светлана наконец сделала первый заказ, «Собачье сердце»:
INSERT INTO orders VALUES (6, 4, '2026-10-09', 'new');
INSERT INTO order_items VALUES (6, 2, 1, 390.00);
SELECT * FROM book_sales WHERE id = 2;
id | title | sold | revenue
----+----------------+------+---------
2 | Собачье сердце | 1 | 390.00
(1 row)
Книга, которой только что не было в отчёте, появилась сама. Ничего обновлять не пришлось: представление выполнило свой запрос заново.
Зачем представления в жизни:
- Не повторять сложный запрос. Логику «выручка без отменённых» описали один раз, и все отчёты берут её отсюда. Поменяется правило, поменяешь одно место.
- Прятать лишнее. Аналитику можно дать доступ к представлению с городами покупателей, но без их имён, и не давать доступ к самой таблице. Как раздают такие права, разберём в уроке про роли.
- Стабильное имя для приложения. Таблицы под представлением можно перестроить, а приложение продолжит читать то же имя с теми же колонками.
урок из курса
Урок из курса «PostgreSQL с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.
Оплата пока не подключена: премиум и курсы открываются промокодом.