Что такое операция GROUP BY в SQL?

Ответ

GROUP BY в SQL — это оператор, который объединяет строки результирующего набора данных, имеющие одинаковые значения в указанных столбцах, в одну сводную запись (группу). Он используется совместно с агрегатными функциями (COUNT, SUM, AVG, MAX, MIN), которые выполняют вычисление для каждой группы.

Базовый синтаксис и пример:

SELECT department_id, 
       COUNT(*) AS num_employees, 
       AVG(salary) AS avg_salary
FROM employees
WHERE hire_date > '2020-01-01' -- Фильтрация ДО группировки (по строкам)
GROUP BY department_id         -- Столбец(цы) для группировки
HAVING AVG(salary) > 50000;   -- Фильтрация ПОСЛЕ группировки (по группам)

Этот запрос:

  1. Берет всех сотрудников, нанятых после 2020 года.
  2. Разбивает их на группы по department_id.
  3. Для каждой группы вычисляет количество сотрудников и среднюю зарплату.
  4. Оставляет только те группы, где средняя зарплата превышает 50000.

Критически важные правила:

  • Все столбцы, перечисленные в SELECT и не являющиеся аргументами агрегатных функций, должны быть включены в GROUP BY.
  • WHERE фильтрует отдельные строки до этапа группировки.
  • HAVING фильтрует уже сформированные группы после группировки. В HAVING можно использовать агрегатные функции.

Пример ошибки:

-- НЕВЕРНО: column 'employees.name' is non-aggregated and not in GROUP BY
SELECT department_id, name, COUNT(*)
FROM employees
GROUP BY department_id;

-- ВЕРНО: либо добавьте name в GROUP BY, либо уберите его из SELECT
SELECT department_id, COUNT(*)
FROM employees
GROUP BY department_id;

Типичное применение: Получение сводной статистики — подсчет, суммирование, нахождение экстремумов по категориям (по отделам, по датам, по регионам).

Ответ 18+ 🔞

А, ну это же классика, блядь! GROUP BY, ёпта! Это как когда ты приходишь в бар, а там куча народа, и ты такой: "Так, блядь, давайте по паспортам соберёмся, кто 90-го года рождения — ко мне, кто 91-го — вон к тому столу!"

Вот смотри, сука, на пальцах. Есть у тебя таблица employees, там все сотрудники вперемешку лежат, как носки в стиралке. А тебе начальство орёт: "Сделай сводную, блядь, по отделам! Сколько людей и сколько они в среднем жрут наших денег!"

И ты пишешь вот эту магию:

SELECT department_id,
       COUNT(*) AS num_employees,
       AVG(salary) AS avg_salary
FROM employees
WHERE hire_date > '2020-01-01'
GROUP BY department_id
HAVING AVG(salary) > 50000;

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

  1. FROM employees: Ты вываливаешь на пол всю таблицу с сотрудниками. Всех, сука, от уборщицы до директора.
  2. WHERE hire_date > '2020-01-01': Ты начинаешь отсеивать мусор. "Так, блядь, старые кадры, 2019 года и раньше — нахуй отсюда! Нам нужны только те, кого наняли после 2020-го". Это фильтрация ДО того, как ты начал кого-то группировать. По отдельным строкам.
  3. GROUP BY department_id: А вот тут начинается цирк. Ты кричишь: "Так, все, чей department_id = 1 — встали в кучку! Чей department_id = 2 — в другую кучку!". И все начинают шаркать ногами и объединяться. Из кучи отдельных строк получается несколько аккуратных групп.
  4. *`SELECT ... COUNT() ... AVG(salary)`**: Теперь ты подходишь к каждой кучке и считаешь. "В первой кучке, блядь, 5 человек. Средняя зарплата у них 75к. Записываем. Во второй кучке 12 человек, средняя 45к. Записываем".
  5. HAVING AVG(salary) > 50000: И финальный акт, блядь! Ты смотришь на свои записи и заявляешь: "Вторая кучка, где средняя 45к — вы мне нахуй не интересны, распидораситесь обратно! Оставляю только те группы, где средняя зарплата больше 50к". Это фильтрация ПОСЛЕ группировки, по уже готовым результатам.

Главное правило, которое все хуёво запоминают: Всё, что ты пишешь в SELECT и это НЕ агрегатная функция (типа COUNT, SUM), должно быть в GROUP BY. Иначе SQL-сервер смотрит на тебя как на идиота и спрашивает: "Чувак, блядь, я сгруппировал по отделам, а ты просишь вывести имя каждого человека. Из какой, сука, строки в группе мне его взять? Их там пять штук!".

Вот так и получается ошибка:

-- НЕВЕРНО: column 'employees.name' is non-aggregated and not in GROUP BY
SELECT department_id, name, COUNT(*)
FROM employees
GROUP BY department_id;

Тут тебе ясно намекают: "Либо добавляй name в GROUP BY (тогда группы будут по отделам И по именам, что бред), либо не выёбывайся и убери его из вывода".

Короче, GROUP BY — это твой инструмент, чтобы из хаоса сделать хоть какую-то статистику, которую можно начальству впендюрить. Главное — не перепутай WHERE (фильтруем строки до группировки) и HAVING (фильтруем группы после). А то будет пиздец и волнение ебать.