SQL Studio / Разборы SQL / Как считать несколько показателей через SUM(CASE WHEN)
Условная агрегация: SUM(CASE WHEN условие THEN число ELSE 0 END) суммирует значение только для подходящих строк. Если требуется количество подходящих строк, суммируйте единицы.
1. Условные счётчики за один запрос
В учебной базе шесть заказов: четыре доставленных, один отменённый, один в обработке.
SELECT COUNT(*) AS orders_total,
SUM(CASE WHEN status = 'delivered' THEN 1 ELSE 0 END) AS delivered_n,
SUM(CASE WHEN status = 'cancelled' THEN 1 ELSE 0 END) AS cancelled_n
FROM orders;
Результат: 6 заказов всего, 4 доставки и 1 отмена. Разница не потерялась: один заказ ещё находится в обработке.
2. Условная сумма денежных показателей
Стоимость заказа хранится в копейках. Сначала суммируем, затем делим на 100.
SELECT
SUM(CASE WHEN status = 'delivered' THEN gross_kopecks ELSE 0 END) / 100.0 AS delivered_gross_rub,
SUM(CASE WHEN status = 'cancelled' THEN gross_kopecks ELSE 0 END) / 100.0 AS cancelled_gross_rub
FROM orders;
| Доставленные | Отменённые |
|---|---|
| 1250 | 450 |
Это стоимость заказов, а не чистые поступления. Для финансового отчёта нужно отдельно проверить платежи и возвраты, иначе можно получить правдоподобную, но неправильную сумму.
3. LEFT JOIN и клиенты с нулём заказов
Хотим увидеть всех клиентов. Считаем заказы по o.order_id, а не через COUNT(*): последний даст единицу для клиента без заказов.
SELECT c.customer_id, c.name,
COUNT(o.order_id) AS orders_n,
SUM(CASE WHEN o.status = 'delivered' THEN 1 ELSE 0 END) AS delivered_n
FROM customers AS c
LEFT JOIN orders AS o ON o.customer_id = c.customer_id
GROUP BY c.customer_id, c.name
ORDER BY c.customer_id;
Анна — (2 заказа, 2 доставки), Борис — (2, 1), Вера — (2, 1), Данил — (0, 0). Условный подсчёт не теряет клиента без заказов.
4. Что произойдёт, если забыть ELSE 0
SELECT
SUM(CASE WHEN status = 'returned' THEN 1 END) AS wrong_null,
SUM(CASE WHEN status = 'returned' THEN 1 ELSE 0 END) AS correct_zero
FROM orders;
Ответ: wrong_null = NULL и correct_zero = 0. Если подходящих строк нет, SUM из одних NULL возвращает NULL. Если исходная таблица совсем пуста, даже ELSE 0 не поможет — используйте COALESCE(SUM(...),0).
Справка: SQLite — CASE и агрегатные функции.
Для последовательной практики на MySQL 8 — курс «SQL для аналитика» на Stepik с итоговой работой и возможностью получить сертификат.