0Pricing
Coding Interview Prep · Урок

Агрегаты без GROUP BY

Узнайте, как обычная агрегатная функция сворачивает целую таблицу в одну строку.

«Агрегаты без GROUP BY» — бесплатный урок Coding Interview Prep на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Coding Interview Prep, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Coding Interview Prep содержит 4 уроков всего.

Одна агрегатная функция — одна строка

На собеседовании часто проверяют базовое понимание с помощью вопроса: «Что происходит при использовании агрегатной функции без GROUP BY?»

Ответ: вся таблица сворачивается в одну строку. Агрегатная функция рассматривает все подходящие строки как одну большую неявную группу. Понимание этой модели «неявной группы» объясняет многие последующие правила, поэтому разберём её внимательно.

Неявная единственная группа

Когда вы записываете отдельную агрегатную функцию без GROUP BY, SQL ведёт себя так, будто существует одна группа, содержащая каждую строку. Результат всегда состоит ровно из одной строки, независимо от размера таблицы — даже если таблица пуста.

Так, SELECT COUNT(*) FROM employees возвращает одну строку с одним числом, обобщающим содержимое всей таблицы.

SELECT COUNT(*) AS total_employees
FROM employees;
-- always returns exactly one row

Несколько агрегатных функций вместе

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

Это стандартный запрос «покажите сводную статистику». Все четыре числа описывают один и тот же полный набор строк.

SELECT
  COUNT(*)     AS num_rows,
  SUM(salary)  AS total_pay,
  AVG(salary)  AS avg_pay,
  MAX(salary)  AS top_pay
FROM employees;

Ошибка при смешивании

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

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

-- ERROR: name is not aggregated and there is no GROUP BY
SELECT name, MAX(salary)
FROM employees;

Почему это неоднозначно

Рассмотрим это на примере нашей таблицы. MAX(salary) сворачивает все строки в одно значение. Но name имеет разное значение в каждой строке. Одна сводная строка не может содержать пять имён в одной ячейке.

База данных отказывается угадывать. Это тот же принцип, что лежит в основе правила GROUP BY: каждый выбранный столбец должен быть либо агрегирован, либо входить в группу. Без GROUP BY разрешены только агрегатные функции.

Нестрогое исключение MySQL

Стоит упомянуть одну особенность диалекта: старый или нестрогий MySQL позволял смешивать такие элементы в запросе и возвращал произвольное имя — не обязательно имя сотрудника с максимальной зарплатой.

Современный MySQL с включённым ONLY_FULL_GROUP_BY (теперь это значение по умолчанию) отклоняет такой запрос, как и остальные СУБД. Упоминание этой особенности показывает знание разных диалектов, но смешанный запрос всегда следует считать неправильным.

Как получить строку с максимальным значением

Как же получить имя самого высокооплачиваемого сотрудника? Не смешивайте агрегатную функцию и столбец. Используйте ORDER BY + LIMIT либо подзапрос, сравнивающий значения с результатом агрегатной функции.

Вариант с ORDER BY/LIMIT проще всего. Вариант с подзапросом хорошо обобщается и возвращает всех сотрудников с одинаковой максимальной зарплатой.

-- Subquery: returns everyone earning the max
SELECT name, salary
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);

Агрегатные функции для пустой таблицы

Это один из пограничных случаев, которые задают на собеседованиях: «Что возвращает отдельная агрегатная функция для пустой таблицы?»

  • COUNT(*) возвращает 0 (одну строку со значением 0).
  • SUM, AVG, MIN, MAX возвращают NULL (одну строку со значением NULL).

Важно, что вы всё равно получаете одну строку, а не ноль строк. Именно такая гарантия одной строки является главным смыслом агрегатной функции без GROUP BY.

SELECT COUNT(*) AS c, SUM(salary) AS s, MAX(salary) AS m
FROM employees
WHERE 1 = 0;
-- one row: c=0, s=NULL, m=NULL

Агрегаты нельзя использовать в WHERE

Из этой модели следует ещё одно правило: нельзя помещать агрегатную функцию в предложение WHERE, потому что WHERE фильтрует отдельные строки до выполнения агрегации.

Чтобы отфильтровать результат агрегатной функции, используйте HAVING (вместе с группировкой) или поместите агрегатную функцию в подзапрос. WHERE выполняется слишком рано в порядке выполнения запроса и поэтому не видит результат агрегации.

-- ERROR: aggregate not allowed in WHERE
-- SELECT * FROM employees WHERE salary > AVG(salary);

-- Correct: compare to the aggregate via subquery
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);

Агрегат без GROUP BY и GROUP BY

Сформулируйте различие самостоятельно:

  • Без GROUP BY: одна неявная группа = вся таблица = ровно одна результирующая строка.
  • С GROUP BY для столбца: одна группа для каждого отдельного значения столбца = одна строка на группу.

Агрегатная функция без GROUP BY — это всего лишь GROUP BY с нулём столбцов группировки. Тот же механизм, но одна большая группа.

-- Whole table: one row
SELECT AVG(salary) FROM employees;

-- Per department: one row each
SELECT department, AVG(salary)
FROM employees
GROUP BY department;

Как это объяснить

Чёткий ответ: «Агрегатная функция без GROUP BY рассматривает весь результирующий набор как одну неявную группу и возвращает ровно одну сводную строку, даже если таблица пуста. Нельзя выбрать вместе с ней неагрегированный столбец, потому что его значение было бы неоднозначным. Чтобы получить строку, соответствующую MAX или MIN, я использую ORDER BY с LIMIT или подзапрос, сравнивающий значения с результатом агрегатной функции».

Быстрая проверка

Предскажите структуру результата.

Повторение

Агрегатные функции без GROUP BY вкратце:

  • Вся таблица становится одной неявной группой → ровно одна результирующая строка.
  • Нельзя смешивать отдельную агрегатную функцию с неагрегированным столбцом.
  • Пустая таблица: COUNT(*) = 0, остальные функции возвращают NULL, но строка всё равно одна.
  • Агрегатные функции нельзя использовать в WHERE; используйте подзапрос или HAVING.
  • Чтобы получить строку, соответствующую MIN/MAX, используйте ORDER BY + LIMIT или подзапрос.

На этом упражнения с агрегатными функциями для собеседования завершены.

Часто задаваемые вопросы

Урок «Агрегаты без GROUP BY» бесплатный?

Да — полный текст урока «Агрегаты без GROUP BY» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Coding Interview Prep, подпишись на CoddyKit PRO. Курс Coding Interview Prep содержит 4 уроков всего.

Чему я научусь в уроке «Агрегаты без GROUP BY»?

Узнайте, как обычная агрегатная функция сворачивает целую таблицу в одну строку. Ты практикуешь Coding Interview Prep с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Coding Interview Prep?

Предыдущий опыт не требуется. Coding Interview Prep на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Агрегаты без GROUP BY»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Coding Interview Prep?

Да. Каждый урок Coding Interview Prep включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. COUNT(*) и COUNT(столбец) и COUNT(DISTINCT)
  2. SUM и AVG с NULL
  3. MIN, MAX и агрегирование нечисловых данных
  4. Агрегаты без GROUP BY
← Назад к Coding Interview Prep