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

Ответ

Агрегатные функции в SQL — это функции, которые выполняют вычисление над набором строк (группой) и возвращают одно результирующее значение. Они используются в сочетании с предложениями SELECT, GROUP BY и HAVING.

Основные агрегатные функции:

  • COUNT() — возвращает количество строк.
    • COUNT(*) — считает все строки, включая NULL.
    • COUNT(column) — считает строки, где значение в column не NULL.
    • COUNT(DISTINCT column) — считает количество уникальных значений.
  • SUM(column) — возвращает сумму значений числового столбца.
  • AVG(column) — возвращает среднее арифметическое значений.
  • MAX(column) / MIN(column) — возвращают максимальное/минимальное значение.

Практические примеры использования:

-- 1. Общая статистика по таблице
SELECT 
    COUNT(*) as total_employees,
    AVG(salary) as average_salary,
    MAX(salary) as max_salary
FROM employees;

-- 2. Группировка с агрегацией (ключевое использование)
SELECT 
    department_id,
    COUNT(*) as emp_count,
    AVG(salary) as avg_salary,
    SUM(salary) as total_budget
FROM employees
WHERE hire_date > '2020-01-01' -- Фильтрация ДО группировки
GROUP BY department_id
HAVING AVG(salary) > 50000; -- Фильтрация ПОСЛЕ группировки

-- 3. Поиск дубликатов с помощью COUNT
SELECT email, COUNT(*) as duplicate_count
FROM users
GROUP BY email
HAVING COUNT(*) > 1;

Важные правила:

  1. Игнорирование NULL: Все агрегатные функции, кроме COUNT(*), игнорируют значения NULL.
  2. WHERE vs HAVING: WHERE фильтрует строки до группировки, HAVING фильтрует результаты после группировки.
  3. Группировка: При использовании GROUP BY в SELECT можно указывать только столбцы для группировки и агрегатные функции.

Ответ 18+ 🔞

Давай разберём эту тему, чтобы она в голове осела не как сухой справочник, а как живая, понятная хуйня.

Представь, что у тебя есть таблица с сотрудниками. Просто куча строк: имя, зп, отдел. И ты такой сидишь и думаешь: «Ну и нахуя мне этот список? Я хочу знать суть!». Вот агрегатные функции — это как раз инструменты, чтобы вытащить эту суть, сжать всю эту простыню данных в одну ёмкую, жирную цифру.

Основные пацаны на районе:

  • COUNT() — этот чувак просто считает. «Сколько у нас людей?». COUNT(*) посчитает всех подряд, даже пустые места. COUNT(зарплата) посчитает только тех, у кого зп указана (NULL — в игноре). А COUNT(DISTINCT отдел) выдаст, в скольких уникальных отделах народ работает. Просто, но охуенно полезно.
  • SUM() — а этот уже с калькулятором. «А сколько мы всем вместе, блядь, денег в месяц отваливаем?». Берёт столбец с числами и плюсует всё в кучу.
  • AVG() — его любимый вопрос: «Ну и как в среднем?». Средняя температура по больнице, средняя зп по отделу. Главное помнить — NULL-ы он игнорирует, так что среднее считается только по тем, у кого значение есть.
  • MAX() / MIN() — два брата-антагониста. Один ищет самого жирного кота в отделе (MAX(зарплата)), другой — самого обделенного (MIN(зарплата)).

А теперь, блядь, магия — группировка!

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

-- Смотри сюда, гений
SELECT 
    department_id, -- Группируем по отделам
    COUNT(*) as emp_count, -- Сколько человек в каждом
    AVG(salary) as avg_salary, -- Средняя зп в каждом
    SUM(salary) as total_budget -- Сколько денег жрёт каждый отдел
FROM employees
GROUP BY department_id; -- Ключевая команда! «Сверни всё по отделам»

И тут появляется два охранника, которые всех путают: WHERE и HAVING.

  • WHERE — это вышибала на входе в клуб. Он фильтрует строки ДО того, как начнётся вся эта групповуха с подсчётами. «Пусть в статистику попадут только те, кого наняли после 2020 года».
  • HAVING — это вышибала уже внутри VIP-зала. Он фильтрует результаты ПОСЛЕ группировки. «Покажи мне только те отделы, где средняя зп больше 50к». Без GROUP BY он вообще не работает, чувак.
SELECT 
    department_id,
    AVG(salary) as avg_sal
FROM employees
WHERE hire_date > '2020-01-01' -- Сначала отфильтруем новых (WHERE)
GROUP BY department_id
HAVING AVG(salary) > 50000; -- Потом отфильтруем богатые отделы (HAVING)

И главное правило, ёпта: Когда делаешь GROUP BY, в твоём SELECT могут быть только два типа вещей:

  1. Столбцы, по которым ты группируешь (department_id).
  2. Агрегатные функции над всеми остальными столбцами (COUNT(*), AVG(salary)).

Если попробуешь впихнуть туда просто name без агрегации — база данных тебе справедливо скажет «Иди нахуй, я не могу угадать, какое именно имя из группы ты хочешь видеть».

Вот и вся философия. Не просто складывай циферки, а думай, какую историю они рассказывают. Удачи, не облажайся!