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"
- Таблицы
tourиplaceне имеют связи по ключам - но каждыйplaceлогически соответствует каждомуtour. - Таблица
protocolимеет составной первичный ключtour_id, place_id- вместе, и два внешних ключа -tour_id,place_id- отдельно. - Поля
tour.numberиtour.name- формально не обязательно уникальные, но логически должны почти всегда и мои тестовые данные содержат только уникальные значения этих полей.
В чём может быть природа такого поведения? По всему, что я знаю - такого быть не должно и запрос должен свалиться с ошибкой - ведь поля tour.number и tour.nameв GROUP BY не содержатся.
Возможно, postgres проводит самостоятельный анализ и сам понимает их допустимость к добавлению в SELECT? Возможно, такого быть не должно и я упускаю потенциальный баг? Если второе правда, почему я не получаю ошибку, хотя по всем правилам должен?
Ответы (1 шт):
Судя по всему ошибка не выдается из-за того что группировка делается по полю 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.
