Часть 5 из 16

После WHERE мы умеем находить подходящие события, но пока показываем только то, что уже записано в таблицах. В этой части научимся выводить новые значения прямо в результате запроса: посчитаем длительность концерта, переведём машинный статус в понятную подпись и обсудим точный тип для цены билета.

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

Считаем длительность

SELECT name,
 TIMESTAMPDIFF(MINUTE,starts_at,ends_at) AS duration_minutes,
 CASE status
  WHEN 'planned' THEN 'Готовится'
  WHEN 'open' THEN 'Билеты продаются'
  WHEN 'finished' THEN 'Завершено'
  ELSE 'Проверьте статус'
 END AS status_label
FROM events;

CASE похож на цепочку условий. Алиас после AS задаёт заголовок вычисляемого столбца.

Поиск по названию

SELECT name FROM events WHERE name LIKE '%ночная%';

Процент означает любое число символов. Начальный процент часто мешает обычному индексу текста, но для небольшой таблицы это не проблема.

Деньги и точность

Стоимость билета будем хранить как DECIMAL(8,2): точное десятичное значение с двумя знаками. FLOAT приближённый и способен давать мелкие ошибки округления.

Время означает локальную зону

DATETIME не хранит часовой пояс. Для одного фестиваля договоримся о местном времени площадки; для международной системы нужно единое правило хранения и преобразования зон. Следующая часть свяжет артистов с событиями через JOIN.

Когда вычислять, а когда сохранять?

Поле duration_minutes зависит от двух других значений: времени начала и окончания. Обычно его не нужно хранить отдельно — иначе после переноса времени длительность может устареть. Вычисляемый столбец в SELECT всегда отражает текущие значения. Сохранять результат отдельно имеет смысл лишь при понятной причине и механизме обновления.

Денежный тип DECIMAL(8,2) означает до восьми цифр всего, включая две после точки. Например, 1234.50 помещается; дробная копейка будет округляться согласно правилам преобразования. В отличие от FLOAT, десятичное значение хранится точно в заданном масштабе, поэтому сумма билетов подходит для DECIMAL.

Попробуйте добавить в SELECT вычисление длительности и CASE-подпись статуса. Сравните их с исходными колонками во вкладке результата: строки таблицы не изменятся, потому что запрос только читает данные. Следом добавим артистов, и вычисления впервые появятся в совместном расписании.

Понимаем точность DECIMAL

В записи DECIMAL(8,2) первое число задаёт максимальное количество цифр всего, второе — сколько цифр будет после десятичной точки. Например, 123456.78 использует все восемь цифр, а более крупная сумма уже не поместится без ошибки или преобразования.

Выбирайте диапазон по реальной верхней границе, а не бесконечно увеличивайте его «на всякий случай».

В SQL десятичный разделитель — точка, даже если phpMyAdmin или ваша локаль показывают запятую в интерфейсе. Для цены пишите 1200.50. Не храните денежную стоимость текстом: тогда сортировка может поставить «900» выше «1200», а сложение потребует преобразований.

Решите, где хранить длительность

Если длительность всегда равна разнице начала и конца, вычисляйте её запросом с TIMESTAMPDIFF, как в примере выше. Если сохранить отдельное поле и забыть обновить его после переноса выступления, база будет содержать две противоречащие друг другу истины.

В следующем уроке соединим таблицы и увидим, как вычисляемые колонки работают рядом с данными из связанных сущностей.

Выбираем хранение и вычисление

Задача Подход Почему
Хранить цену DECIMAL(8,2) Точная десятичная стоимость
Получать длительность TIMESTAMPDIFF в SELECT Не дублируем вычисляемое значение
Показывать текст статуса CASE в SELECT Исходный статус остаётся машинным

Если значение можно однозначно получить из уже сохранённых данных, сначала спросите себя, нужно ли хранить его ещё раз.

← Предыдущая статья: WHERE и даты MySQL: находим нужные события

Следующая статья: JOIN в MySQL: связываем артистов, события и площадки →