Часть 13 из 16

В предыдущей части мы сделали две SQL-команды одной неделимой операцией. Теперь посмотрим на другую задачу: отчёт о продажах нужен организатору снова и снова, а длинный JOIN с подсчётами неудобно копировать и поддерживать.

Мы сохраним проверенную логику в представлении — виртуальной таблице, которая каждый раз показывает актуальный результат запроса. Разберём, что view упрощает, чего он не делает и почему не заменяет ни таблицу, ни резервную копию.

Создаём сводку событий

CREATE OR REPLACE VIEW v_event_sales AS
SELECT e.event_id,e.name AS event_name,v.name AS venue_name,
 e.starts_at,COALESCE(s.sold_count,0) AS sold_count,
 COALESCE(s.revenue,0.00) AS revenue
FROM events AS e
JOIN venues AS v ON v.venue_id=e.venue_id
LEFT JOIN (
 SELECT event_id,COUNT(*) AS sold_count,SUM(price) AS revenue
 FROM ticket_sales GROUP BY event_id
) AS s ON s.event_id=e.event_id;

Продажи агрегируются отдельно: так число артистов не умножает сумму. LEFT JOIN сохраняет события без билетов, COALESCE показывает ноль.

Используем как источник

SELECT event_name,venue_name,sold_count,revenue
FROM v_event_sales
WHERE starts_at >= '2026-10-30 00:00:00'
ORDER BY revenue DESC;

phpMyAdmin покажет view среди объектов базы. Запрос к нему выглядит как чтение таблицы.

Чего представление не делает

Оно не хранит вторую копию строк и не ускоряет запрос автоматически: MySQL исполняет определение при чтении. Представления с агрегатами обычно не предназначены для UPDATE. Для восстановления базы они не заменяют дамп.

Следующий уровень аналитики

GROUP BY схлопывает строки, а иногда нужно сохранить каждый слот и добавить его место в расписании. В следующей части используем оконные функции.

Когда представление полезно

Представление — сохранённый SELECT, а не сохранённый результат. Это делает его удобным общим именем для часто используемой логики: редактору не нужно помнить три JOIN и способ подсчёта выручки. Если исходные продажи изменились, следующий запрос к view пересчитает данные согласно его определению.

Откройте представление в phpMyAdmin так же, как таблицу, или запросите только нужные колонки. Чтобы изменить его логику, выполните CREATE OR REPLACE VIEW с новой версией запроса. Сначала проверьте SELECT самостоятельно, иначе ошибочное определение сразу станет новым отчётным интерфейсом.

Представление не всегда можно редактировать

Простое представление над одной таблицей иногда допускает UPDATE, но агрегат, GROUP BY и несколько объединённых источников часто делают его не обновляемым. Для курса мы используем его только для чтения.

Права доступа к view зависят от настроек безопасности и владельца объекта: наличие представления само по себе не скрывает таблицу от пользователя.

Потренируйтесь: запросите из v_event_sales только события с выручкой выше 1000 и отсортируйте по дате. Затем сравните результат с исходным агрегатным запросом. Следующая часть покажет другой подход для аналитики — окна, которые добавляют вычисления, не теряя отдельные строки.

View как контракт отчётного слоя

Полезное представление имеет устойчивые имена и смысл полей. Например, revenue всегда означает сумму цены проданных билетов, а не прибыль за вычетом расходов. Дайте колонкам алиасы и зафиксируйте смысл в документации команды.

Если завтра появится налог или возврат, понадобится решить, как они учитываются, прежде чем менять формулу.

Перед заменой определения проверьте старый SELECT, сравните количество событий и несколько сумм. CREATE OR REPLACE VIEW обновляет текст представления, но не создаёт историю его прежних версий. В phpMyAdmin можно посмотреть его определение через структуру объекта или SQL-команду SHOW CREATE VIEW v_event_sales;.

Упражнение: добавьте в запрос отчёта условие по одной площадке, но не переписывайте сам view. Разделение постоянной логики и фильтра конкретного отчёта облегчает дальнейшее обслуживание.

View и обычная таблица — не одно и то же

Объект Что хранит Когда подходит
Таблица Сами строки данных Когда это отдельные сохраняемые факты
Представление Определение SELECT Когда отчётную логику используют повторно

Изменение продажи отразится в следующем чтении представления, потому что view пересчитывает результат из исходных таблиц.

← Предыдущая статья: Транзакции MySQL: отмечаем билет без частичных изменений

Следующая статья: Оконные функции MySQL: ранжируем расписание и выручку →