Что такое агрегатная функция в SQL?

Ответ

Агрегатная функция в SQL — это функция, которая выполняет вычисление над набором строк и возвращает единственное значение. Я постоянно использую их при работе с базами данных для анализа и суммирования данных.

Основные агрегатные функции, которые применяю чаще всего:

Функция Назначение Пример использования
COUNT() Подсчёт количества строк COUNT(*) — все строки, COUNT(column) — не-NULL значения
SUM() Сумма числовых значений SUM(price * quantity) для подсчёта общей стоимости
AVG() Среднее арифметическое AVG(rating) для средней оценки товара
MAX() Максимальное значение MAX(created_at) для последней записи
MIN() Минимальное значение MIN(price) для самой низкой цены
GROUP_CONCAT() Конкатенация строк (MySQL) GROUP_CONCAT(name SEPARATOR ', ') для списка

Практические примеры из моих проектов:

-- Анализ продаж за месяц
SELECT 
    product_id,
    COUNT(*) as orders_count,
    SUM(quantity) as total_quantity,
    SUM(price * quantity) as total_revenue,
    AVG(price) as average_price
FROM orders
WHERE order_date >= '2024-01-01' AND order_date < '2024-02-01'
GROUP BY product_id
HAVING total_revenue > 1000  -- Фильтрация после агрегации
ORDER BY total_revenue DESC;
-- Статистика по пользователям
SELECT 
    DATE(created_at) as signup_date,
    COUNT(*) as new_users,
    MIN(created_at) as first_signup,
    MAX(created_at) as last_signup
FROM users
GROUP BY DATE(created_at)
ORDER BY signup_date DESC;

Важные особенности работы с агрегатными функциями:

  1. Группировка с GROUP BY: Без GROUP BY агрегатные функции применяются ко всей таблице:

    -- Общая статистика по всей таблице
    SELECT 
        COUNT(*) as total_users,
        AVG(age) as average_age,
        MAX(last_login) as latest_login
    FROM users;
  2. Обработка NULL: Большинство агрегатных функций игнорируют NULL значения. COUNT(column) не считает NULL, AVG() их не учитывает.

  3. Фильтрация результатов: WHERE фильтрует строки до агрегации, HAVING — после:

    -- Только активные пользователи, сгруппированные по странам
    SELECT 
        country,
        COUNT(*) as active_users
    FROM users
    WHERE last_login > DATE_SUB(NOW(), INTERVAL 30 DAY)  -- До агрегации
    GROUP BY country
    HAVING active_users >= 10  -- После агрегации
  4. Вложенные агрегации в PHP: Иногда выполняю дополнительную агрегацию уже на стороне PHP:

    $stmt = $pdo->query("SELECT category, SUM(amount) as category_total FROM transactions GROUP BY category");
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
    // Дополнительный расчёт на PHP
    $grandTotal = array_sum(array_column($results, 'category_total'));
    $averagePerCategory = $grandTotal / count($results);

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

Ответ 18+ 🔞

Да ты посмотри, какие штуки в SQL есть, ебать мои старые костыли! Агрегатные функции — это ж как волшебная палочка для баз данных. Вместо того чтобы тащить в код овердохуища строк и там уже с ними мучиться, ты сразу на стороне базы всё посчитаешь и получишь одно готовое значение. Удобно же, ёпта!

Вот эти штуки я постоянно юзаю, без них нихуя не сделаешь:

Функция Зачем нужна Как применяю
COUNT() Посчитать сколько чего COUNT(*) — всё подряд, COUNT(column) — только где не NULL
SUM() Всё сложить SUM(price * quantity) — чтобы понять, сколько бабла срубил
AVG() Среднюю температуру по больнице найти AVG(rating) — ну, типа, какая в среднем оценка
MAX() Найти самый большой MAX(created_at) — когда последняя запись прилетела
MIN() Найти самый маленький MIN(price) — а где у нас самый дешёвый товар?
GROUP_CONCAT() Склеить строки в одну (в MySQL) GROUP_CONCAT(name SEPARATOR ', ') — получить список через запятую

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

-- Разбор полётов по продажам за месяц
SELECT 
    product_id,
    COUNT(*) as orders_count, -- сколько раз покупали
    SUM(quantity) as total_quantity, -- сколько штук всего ушло
    SUM(price * quantity) as total_revenue, -- вот он, наш профит!
    AVG(price) as average_price -- средний чек, грубо говоря
FROM orders
WHERE order_date >= '2024-01-01' AND order_date < '2024-02-01' -- берём только январь
GROUP BY product_id -- группируем по товарам
HAVING total_revenue > 1000  -- а это фильтр УЖЕ после того, как всё посчитали
ORDER BY total_revenue DESC; -- и сортируем от большего к меньшему
-- Статистика по регистрации пользователей
SELECT 
    DATE(created_at) as signup_date, -- дата без времени
    COUNT(*) as new_users, -- сколько народу пришло
    MIN(created_at) as first_signup, -- первый за день
    MAX(created_at) as last_signup -- последний за день
FROM users
GROUP BY DATE(created_at) -- группируем по дате
ORDER BY signup_date DESC;

А теперь, чувак, важные фишки, без которых обосрёшься:

  1. GROUP BY — наше всё: Без него агрегатная функция схлопнет всю таблицу в одну строку, ядрёна вошь!

    -- Общая картина по юзерам
    SELECT 
        COUNT(*) as total_users, -- всего людей
        AVG(age) as average_age, -- средний возраст
        MAX(last_login) as latest_login -- кто последний заходил
    FROM users; -- Без GROUP BY — одна строка на выходе
  2. NULL — его величество: Большинство функций на NULL просто забивают болт. COUNT(column) их не видит, AVG() тоже. Помни об этом.

  3. WHERE и HAVING — два больших различия: Это пиздец как важно. WHERE фильтрует строки ДО того, как их посчитают. HAVING фильтрует УЖЕ посчитанные агрегированные результаты.

    -- Берём только активных за месяц, группируем по странам
    SELECT 
        country,
        COUNT(*) as active_users
    FROM users
    WHERE last_login > DATE_SUB(NOW(), INTERVAL 30 DAY)  -- Фильтр ДО группировки
    GROUP BY country
    HAVING active_users >= 10  -- Фильтр ПОСЛЕ группировки (уже по результату COUNT)
  4. Иногда SQL'ем не вытянешь — допиливаем на PHP: Бывает, что после группировки нужно ещё раз всё проагрегировать. Тогда тянем в код и доделываем.

    $stmt = $pdo->query("SELECT category, SUM(amount) as category_total FROM transactions GROUP BY category");
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
    // Допиливаем на PHP
    $grandTotal = array_sum(array_column($results, 'category_total')); // Общая сумма по всем категориям
    $averagePerCategory = $grandTotal / count($results); // Среднее на категорию

Короче, агрегатные функции — это мощнейший инструмент, чтобы не грузить приложение кучей данных, а сразу получать выжимку. База данных справится с этим обычно в разы быстрее, чем твой код. Пользуйся на здоровье, волнение ебать!