Урок 4 из 8 · 20 мин · обновлено

Итоги по таблице: COUNT, SUM, AVG и пустые значения NULL

Как посчитать количество строк, сумму, среднее, минимум и максимум, округлить результат через ROUND, что такое NULL, почему его нельзя сравнивать знаком = и как подставить значение через COALESCE.

Одно число вместо списка

На вопрос «сколько у нас заказов» не нужен список из девяти строк — нужен один ответ. Такие ответы дают агрегатные функции: они сворачивают много строк в одно значение.

Функция Что считает
COUNT(*) сколько строк
SUM(столбец) сумму значений
AVG(столбец) среднее
MIN(столбец), MAX(столбец) наименьшее и наибольшее
SQL
SELECT COUNT(*) FROM orders;
Результат
COUNT(*)
9
SQL
SELECT SUM(amount) FROM orders;
Результат
SUM(amount)
6170

В эту сумму попал и отменённый заказ, а выручка — это деньги за неотменённые. Добавим WHERE: условие отбирает строки раньше, чем считается итог.

SQL
SELECT SUM(amount) AS revenue FROM orders WHERE status <> 'отменён';
Результат
revenue
5280

Несколько агрегатов можно собрать в одну строку сводки — каждый со своим именем через AS:

SQL
SELECT ROUND(AVG(price), 2) AS avg_price,
       MIN(price) AS min_price,
       MAX(price) AS max_price
FROM books;
Результат
avg_price | min_price | max_price
690.0     | 450       | 1200

Округление

Среднее редко получается ровным. Средняя сумма всех заказов — 6170, делённое на 9, — длинная дробь 685,5555… Для отчёта её округляют функцией ROUND: первый аргумент — что округлить, второй — сколько знаков оставить после точки.

SQL
SELECT ROUND(AVG(amount), 2) AS avg_check FROM orders;
Результат
avg_check
685.56

Дробную часть SQL отделяет точкой, а не запятой: так записывают числа и в запросах, и в результатах.

NULL: значение неизвестно

У клиентки Дины не заполнен город. В базе на этом месте лежит NULL — особая отметка «значение неизвестно». Это не ноль и не пустая строка: про ноль мы знаем, что он ноль, а про NULL не знаем ничего.

Отсюда главная особенность: с NULL нельзя сравнивать знаком =. «Неизвестно равно неизвестно?» — ответ тоже «неизвестно», и строка в результат не попадает:

SQL
SELECT name FROM customers WHERE city = NULL;
Результат
name
(0 строк)

Для пустых значений есть специальные проверки IS NULL и IS NOT NULL:

SQL
SELECT name FROM customers WHERE city IS NULL;
Результат
name
Дина

Агрегаты и NULL

Агрегатные функции пропускают NULL. Это хорошо видно на COUNT:

SQL
SELECT COUNT(*) AS all_customers, COUNT(city) AS with_city FROM customers;
Результат
all_customers | with_city
6             | 5

COUNT(*) посчитал все строки, а COUNT(city) — только те, где город заполнен. Так же ведут себя SUM, AVG, MIN и MAX: пустые значения в расчёт не идут. Разница между двумя счётчиками — быстрый способ найти дыры в данных.

Чтобы в отчёте вместо NULL стояло понятное слово, используют COALESCE. Функция возвращает первое заполненное значение из списка:

SQL
SELECT name, COALESCE(city, 'не указан') AS city FROM customers;
Результат
name  | city
Анна  | Москва
Борис | Казань
Вера  | Москва
Глеб  | Пермь
Дина  | не указан
Егор  | Казань

Таблица при этом не изменилась: у Дины в базе по-прежнему NULL, а «не указан» существует только в ответе.

Попробуйте сами. Соберите одной строкой сводку по доставленным заказам: сколько их, на какую сумму, средний чек с округлением до двух знаков и самый крупный заказ.

Решение
SQL
SELECT COUNT(*) AS orders_count,
       SUM(amount) AS revenue,
       ROUND(AVG(amount), 2) AS avg_check,
       MAX(amount) AS max_order
FROM orders
WHERE status = 'доставлен';
Результат
orders_count | revenue | avg_check | max_order
6            | 4260    | 710.0     | 1200

Сначала WHERE оставил шесть доставленных заказов, затем четыре агрегата посчитали итоги по ним. Средний чек получился ровным: 4260 делится на 6 без остатка.

Мини-тест: проверьте себя

Закрепите урок: несколько вопросов, разбор ответов — в конце.

  1. Что вернёт SELECT COUNT(*) FROM orders, если в таблице девять заказов?

  2. Запрос SELECT SUM(amount) FROM orders WHERE status <> 'отменён'. В каком порядке работает база?

  3. Как найти клиентов, у которых не заполнен город?

  4. В таблице шесть клиентов, у одного не заполнен город. Что покажут COUNT(*) и COUNT(city)?

  5. Что делает COALESCE(city, 'не указан')?