Postgres. Применяю GROUP BY, но могу получить поля не отмеченные в GROUP BY

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

Запрос:

SELECT
    "tour"."number",
    "tour"."name",
    COUNT ( "protocol" ) AS "Protocols processed",
    COUNT ( "place" ) AS "Protocols total" 
FROM
    "tour"
    CROSS JOIN "place"
    LEFT JOIN "protocol" ON "protocol"."tour_id" = "tour"."id" 
    AND "protocol"."place_id" = "place"."id" 
WHERE
    "place"."editor_id" = 1
GROUP BY
    "tour"."id" 
ORDER BY
    "tour"."number"
  1. Таблицы tour и place не имеют связи по ключам - но каждый place логически соответствует каждому tour.
  2. Таблица protocol имеет составной первичный ключ tour_id, place_id - вместе, и два внешних ключа - tour_id, place_id - отдельно.
  3. Поля tour.number и tour.name - формально не обязательно уникальные, но логически должны почти всегда и мои тестовые данные содержат только уникальные значения этих полей.

Схема: введите сюда описание изображения

В чём может быть природа такого поведения? По всему, что я знаю - такого быть не должно и запрос должен свалиться с ошибкой - ведь поля tour.number и tour.nameв GROUP BY не содержатся.

Возможно, postgres проводит самостоятельный анализ и сам понимает их допустимость к добавлению в SELECT? Возможно, такого быть не должно и я упускаю потенциальный баг? Если второе правда, почему я не получаю ошибку, хотя по всем правилам должен?


Ответы (1 шт):

Автор решения: newman

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

Попробовал на имеющейся у меня базе. Запрос вида

SELECT id, name, profile_id FROM table GROUP BY id

Выполняется без ошибок.

А вот запрос

SELECT id, name, profile_id FROM table GROUP BY profile_id

Уже выдает ошибку ОШИБКА: колонка "table.id" должна фигурировать в предложении GROUP BY или использоваться в агрегатной функции

P.S.: Этот момент описан в документации: https://postgrespro.ru/docs/postgresql/9.5/queries-table-expressions#queries-group

Если бы в таблице products по столбцу product_id был создан первичный ключ, тогда в данном примере было бы достаточно сгруппировать строки по product_id, так как название и цена продукта функционально зависят от кода продукта и можно однозначно определить, какое название и цену возвращать для каждой группы по ID.

→ Ссылка