Группа по указанному столбцу в PostgreSQL
Возможно, этот вопрос немного глуп, но я в замешательстве.
Как группировать записи по указанному столбцу?:)
Item.group(:category_id)
не работает...
В нем говорится:
ActiveRecord:: StatementInvalid: PGError: ERROR: столбец "items.id" должен появиться в предложении GROUP BY или использоваться в агрегатной функции LINE 1: SELECT "items". * FROM "items" GROUP BY category_id
Какую функцию агрегата я должен использовать?
Пожалуйста, не могли бы вы привести простой пример.
Ответы
Ответ 1
Вам нужно будет определить, как группировать значения, которые имеют один и тот же category_id
. Объединить их? Вычислить сумму?
Чтобы создать список значений, разделенных запятыми, ваш оператор может выглядеть так:
SELECT category_id
,string_agg(col1, ', ') AS col1_list
,string_agg(col2, ', ') AS col2_list
FROM items
GROUP BY category_id
Вам нужен Postgres 9.0 или новее для string_agg(col1, ', ')
.
В более старых версиях вы можете заменить array_to_string(array_agg(col1), ', ')
. Более общие функции здесь.
Чтобы агрегировать значения в PostgreSQL, это явно отличный подход, а не агрегирование значений в клиенте. Postgres работает очень быстро и сокращает (сетевой) трафик.
Ответ 2
Вы можете использовать sum
, avg
, count
или любую другую функцию агрегации. Подробнее об этой теме вы можете найти здесь.
Но, похоже, вам не нужно использовать SQL-группировку.
Попробуйте взять все записи, а затем используйте Array#collect
для группировки Item
на category_id
Ответ 3
Группирование в SQL означает, что сервер группирует одну или несколько записей из таблицы базы данных в одну результирующую строку. Итак, если вы, например, group by category_id
, у вас может быть несколько записей, соответствующих данной категории, поэтому вы не можете ожидать, что база данных вернет столбцы all из таблицы (что означает SELECT *
фактически делает).
Вместо этого, когда вы используете GROUP BY
, вы можете SELECT
:
- столбцы, которые вы сгруппировали, и/или
- совокупные функции, выполняемые во всех записях, относящихся к результирующей группе
В зависимости от того, что вам нужно, измените свой .select
соответственно.