SQLLab
Все статьи

Агрегатные функции SQL: COUNT, SUM, AVG, MIN, MAX

Агрегатные функции SQL: COUNT, SUM, AVG, MIN, MAX — синтаксис и примеры. Как считать, суммировать и анализировать данные с GROUP BY.

22 марта 2026 г.·3 мин чтения·

Агрегатные функции — инструмент для вычислений по группам строк. Без них невозможно посчитать выручку, найти среднее или найти максимальное значение.

Основные функции

COUNT — подсчёт строк

SELECT COUNT(*) FROM orders;          -- все строки
SELECT COUNT(email) FROM users;       -- строки где email не NULL
SELECT COUNT(DISTINCT city) FROM users; -- уникальные города

COUNT(*) считает все строки включая NULL. COUNT(колонка) — только строки где значение не NULL.

SUM — сумма

SELECT SUM(amount) FROM orders;
SELECT SUM(amount) FROM orders WHERE status = 'paid';

Игнорирует NULL. Если все значения NULL — возвращает NULL.

AVG — среднее значение

SELECT AVG(price) FROM products;
SELECT ROUND(AVG(salary), 2) FROM employees;

Тоже игнорирует NULL. Это важно: AVG(10, NULL, 20) = 15, а не 10.

MIN / MAX — минимум и максимум

SELECT MIN(price), MAX(price) FROM products;
SELECT MIN(created_at) AS first_order FROM orders;
SELECT MAX(created_at) AS last_order FROM orders;

Работают с числами, датами и строками (лексикографически).

GROUP BY — группировка

Агрегатные функции становятся по-настоящему полезными с GROUP BY:

-- Выручка по категориям
SELECT category, SUM(price) AS revenue
FROM products
GROUP BY category;
-- Статистика заказов по пользователям
SELECT
    user_id,
    COUNT(*)        AS total_orders,
    SUM(amount)     AS total_spent,
    AVG(amount)     AS avg_order,
    MIN(created_at) AS first_order,
    MAX(created_at) AS last_order
FROM orders
GROUP BY user_id;

HAVING — фильтрация групп

WHERE фильтрует строки до GROUP BY. HAVING — после:

-- Только пользователи с более чем 5 заказами
SELECT user_id, COUNT(*) AS orders
FROM orders
GROUP BY user_id
HAVING COUNT(*) > 5;

-- Категории с выручкой больше 100 000
SELECT category, SUM(amount) AS revenue
FROM orders
GROUP BY category
HAVING SUM(amount) > 100000
ORDER BY revenue DESC;

Комбинированные вычисления

SELECT
    category,
    COUNT(*)                               AS products_count,
    SUM(price)                             AS total_revenue,
    ROUND(AVG(price), 0)                   AS avg_price,
    MAX(price) - MIN(price)                AS price_range,
    ROUND(100.0 * SUM(price) / SUM(SUM(price)) OVER (), 1) AS revenue_share_pct
FROM products
GROUP BY category
ORDER BY total_revenue DESC;

Условная агрегация (CASE WHEN внутри функции)

Мощный приём — считать только строки удовлетворяющие условию:

SELECT
    COUNT(*)                                            AS total,
    COUNT(CASE WHEN status = 'paid'      THEN 1 END)   AS paid,
    COUNT(CASE WHEN status = 'cancelled' THEN 1 END)   AS cancelled,
    SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END) AS paid_revenue
FROM orders;

Агрегаты с NULL

-- Таблица: 10, 20, NULL, 30
SELECT
    COUNT(*)     AS total_rows,  -- 4
    COUNT(value) AS non_null,    -- 3
    SUM(value)   AS sum,         -- 60 (NULL игнорируется)
    AVG(value)   AS avg;         -- 20 (60/3, не 60/4!)

STRING_AGG — объединить строки

-- Список сотрудников по отделам
SELECT
    department,
    STRING_AGG(name, ', ' ORDER BY name) AS employees
FROM employees
GROUP BY department;

Порядок выполнения

FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT

Поэтому:

  • В WHERE нельзя использовать алиасы из SELECT
  • В HAVING можно использовать агрегаты
  • В ORDER BY можно использовать алиасы из SELECT
SELECT department, COUNT(*) AS emp_count
FROM employees
WHERE salary > 50000          -- здесь нельзя использовать emp_count
GROUP BY department
HAVING COUNT(*) > 3           -- здесь можно
ORDER BY emp_count DESC;      -- здесь можно

Похожие статьи

Попробуй на практике

Тренажёр с реальными задачами — бесплатно и без регистрации

Открыть тренажёр →