Почему нельзя выбрать колонку без агрегата при 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.
- Думают, что ошибка — это придирка базы. На самом деле это защита от недетерминированного результата.
Потренируй этот вопрос с ИИ-интервьюером
Читать разбор полезно, а отвечать вслух под давлением — совсем другое. ИИ-интервьюер задаст этот и смежные вопросы, будет копать глубже и разберёт твои ответы. Первое короткое интервью — бесплатно.
Пройти собеседование бесплатно