Агрегатные функции

GROUP BY с соединением таблиц

Немного усложним запрос про получение количества товаров в категории из предыдущего задания. Исходный запрос:

SELECT category_id,
       count(*) as count_products
  FROM product
 GROUP BY category_id

Идентификаторы малоинформативны и обычно никому не интересны. Давай в дополнение к идентификатору категории добавим еще название. Для этого нужно присоединить таблицу category:

SELECT p.category_id,
       c.name,
       count(*) AS count_products
  FROM product p
  JOIN category c
    ON c.category_id = p.category_id
 GROUP BY p.category_id
 ORDER BY p.category_id

Но в результате получим ошибку:

column "c.name" must appear in the GROUP BY clause or be used in an aggregate function

Ошибка возникла потому, что мы в списке выборки указали c.name, но не добавили это поле в GROUP BY. Исправим это:

SELECT p.category_id,
       c.name,
       count(*) AS count_products
  FROM product p
  JOIN category c
    ON c.category_id = p.category_id
 GROUP BY p.category_id, c.name
 ORDER BY p.category_id
category_idnamecount_products
3Бытовая техника2
5Фотоаппараты2
6Игровые консоли3
7Аудиотехника1

P.S. Ошибка бы не возникла, если вместо

GROUP BY p.category_id

написать

GROUP BY c.category_id

СУБД PostgreSQL поймет, что c.category_id является первичным ключом в таблице category и по c.category_id можно однозначно определить c.name. Но так лучше не делать, т.к. в других версиях PostgreSQL это может не работать, как это не работает в других СУБД, например в Oracle.

Если выражение используется в списке выборки, то его нужно включить в GROUP BY, либо вызвать агрегатную функцию от этого выражения. Обратное не требуется: использованное в GROUP BY выражение не обязательно должно присутствовать в списке выборки. В нашем запросе category_id можно было не включать в список выборки SELECT, но в GROUP BY его стоит оставить (название категории может повторяться в рамках таблицы category, и если в GROUP BY оставить только c.name, то останется только одна строка с таким названием, а количество товаров будет равно количеству товаров во всех категориях с таким названием).

    ПредыдущаяСледующая