SQL-вопросы на собеседовании аналитика данных
SQL·junior

Почему нельзя выбрать колонку без агрегата при GROUP BY?

Короткий ответ

После GROUP BY одна строка результата — это целая группа исходных строк. Колонка, по которой не группировали и которую не завернули в агрегат, внутри группы может иметь много разных значений, и база не знает, какое из них показать. Поэтому в SELECT допустимы только поля из GROUP BY и агрегаты над остальными.

Тот случай, когда ошибка column must appear in the GROUP BY clause пугает джуна, а на деле база задаёт очень разумный вопрос: «какое из значений тебе показать?».

Как рассуждать

Представь, что происходит при группировке. GROUP BY схлопывает много строк в одну строку-группу. В результате каждая группа — это одна строчка вывода.

Теперь спроси себя про каждую колонку в SELECT: «у этой группы такое значение одно или их несколько?». Если группируешь по рейтингу, то для группы «R» поле rating одно на всю группу — его показать можно. А поле title внутри группы «R» разное у каждого фильма — какое из 195 названий выводить в одну ячейку? База не угадывает и честно бросает ошибку.

Значит, правило выводится само: в SELECT можно либо поля, по которым группировали (у них в группе одно значение), либо агрегаты — они как раз схлопывают набор значений в одно число.

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

Потому что строка результата после GROUP BY соответствует целой группе, а не одной исходной строке. Колонка вне GROUP BY и вне агрегата внутри группы может быть многозначной — база не может выбрать за тебя.

Правильно:

SELECT rating, count(*) AS films, avg(length) AS avg_len
FROM film
GROUP BY rating;

Здесь rating — из GROUP BY (одно значение на группу), count и avg — агрегаты. Всё определённо.

Неправильно — и упадёт с ошибкой:

SELECT rating, title, count(*)
FROM film
GROUP BY rating;   -- title многозначен внутри группы rating

Если название всё же нужно — реши, какое именно: max(title), «первое по алфавиту», или сначала определись, что группировать надо было по-другому. Часто это сигнал, что тебе вообще нужна не группировка, а оконная функция: она добавляет агрегат рядом со строкой, не схлопывая её.

Дополнительный балл — упомянуть особенность стандарта: если колонка функционально зависит от первичного ключа в GROUP BY, некоторые СУБД её пропускают. Но опираться на это не стоит — Postgres в общем случае строг.

Частые ошибки

  • Пытаются «просто добавить колонку», не понимая, что запрос стал агрегатным. В агрегатном запросе других полей, кроме групп и агрегатов, не бывает.
  • Заворачивают лишнее поле в случайный агрегат (min, max), лишь бы прошло — и получают бессмысленное значение, не связанное с остальной строкой.
  • Путают, где фильтровать группы: условие на агрегат идёт в HAVING, а не в WHERE — это отдельная классика, чем WHERE отличается от HAVING.
  • Думают, что ошибка — это придирка базы. На самом деле это защита от недетерминированного результата.

Потренируй этот вопрос с ИИ-интервьюером

Читать разбор полезно, а отвечать вслух под давлением — совсем другое. ИИ-интервьюер задаст этот и смежные вопросы, будет копать глубже и разберёт твои ответы. Первое короткое интервью — бесплатно.

Пройти собеседование бесплатно

Смежные вопросы