Собесов

Агрегатные функции без GROUP BY: можно ли

SQLАгрегацияЛёгкаяJunior

Условие

Какие из утверждений об агрегатных функциях в SELECT-запросе верны?

  • (а) можно использовать без GROUP BY
  • (б) их нельзя использовать в WHERE
  • (в) их нельзя использовать в HAVING
  • (г) их нельзя использовать в SELECT

Решение

Верны (а) и (б).

(а) Без GROUP BY — да, можно

Агрегат без GROUP BY работает как «вся таблица — одна группа»:

SELECT COUNT(*), AVG(salary), MAX(salary)
FROM   employees;
-- одна строка с тремя числами

Без GROUP BY нельзя смешивать агрегат и не-агрегат:

-- ошибка: department не агрегат и не в GROUP BY
SELECT department, COUNT(*)
FROM employees;

(б) В WHERE — нельзя

WHERE выполняется до агрегации (см. порядок выполнения). Поэтому агрегат там не вычислен и недоступен.

-- ошибка
SELECT * FROM employees WHERE COUNT(*) > 5;

Обходной путь — подзапрос или window function:

SELECT * FROM (
  SELECT *, COUNT(*) OVER () AS cnt FROM employees
) t WHERE cnt > 5;

(в) В HAVING — наоборот, можно и нужно

SELECT department, COUNT(*)
FROM employees
GROUP BY department
HAVING COUNT(*) > 3;

(г) В SELECT — можно

Это очевидно: SELECT COUNT(*) FROM t; — самый частый запрос.

Можно ли в ORDER BY

Да, в ORDER BY агрегат разрешён:

SELECT department, COUNT(*) AS cnt
FROM employees
GROUP BY department
ORDER BY COUNT(*) DESC;

Window functions — отдельная история

COUNT(*) OVER (PARTITION BY ...) — это окно, не агрегат в обычном смысле. Можно использовать в SELECT и ORDER BY, но нельзя в WHERE (и в HAVING тоже, потому что окно вычисляется после).

Подводные камни

  1. SELECT name, COUNT(*) FROM t без GROUP BY — синтаксическая ошибка в строгом режиме. MySQL до 5.7 разрешал, выдавая случайное значение name.
  2. COUNT(*) пустой таблицы = 0, но SUM/AVG вернут NULL. Заворачивайте в COALESCE, если нужна 0.
  3. HAVING без GROUP BY — валиден; работает над всем результатом как над одной группой.

Эталонный ответ

Верны утверждения (а) и (б): агрегат можно использовать без GROUP BY (тогда вся таблица — одна группа), но нельзя в WHERE (фильтрация по строкам происходит до агрегации).

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти