PostgreSQL - должен присутствовать в предложении GROUP BY или использоваться в статистической функции.

Я получаю эту ошибку в режиме pg production, но она нормально работает в режиме разработки sqlite3.

 ActiveRecord::StatementInvalid in ManagementController#index

PG::Error: ERROR:  column "estates.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT "estates".* FROM "estates"  WHERE "estates"."Mgmt" = ...
               ^
: SELECT "estates".* FROM "estates"  WHERE "estates"."Mgmt" = 'Mazzey' GROUP BY user_id

@myestate = Estate.where(:Mgmt => current_user.Company).group(:user_id).all

4 ответа

Решение
@myestate1 = Estate.where(:Mgmt => current_user.Company)
@myestate = @myestate1.select("DISTINCT(user_id)")

это то, что я сделал

Если user_id это ПЕРВИЧНЫЙ КЛЮЧ, тогда вам нужно обновить PostgreSQL; более новые версии будут правильно обрабатывать группировку по первичному ключу.

Если user_id не является ни уникальным, ни первичным ключом для рассматриваемого отношения 'estates', тогда этот запрос не имеет особого смысла, так как PostgreSQL не может узнать, какое значение вернуть для каждого столбца estates где несколько строк разделяют одно и то же user_id, Вы должны использовать агрегатную функцию, которая выражает то, что вы хотите, например, min, max, avg, string_agg, array_aggи т. д. или добавьте интересующие вас столбцы в GROUP BY,

Вы также можете перефразировать запрос, чтобы использовать DISTINCT ON и ORDER BY если вы действительно хотите выбрать несколько произвольную строку, хотя я действительно сомневаюсь, что это можно выразить через ActiveRecord.

Некоторые базы данных, включая SQLite и MySQL, просто выбирают произвольную строку. Команда PostgreSQL считает, что это неправильно и небезопасно, поэтому PostgreSQL следует стандарту SQL и считает такие запросы ошибочными.

Если у вас есть:

col1    col2
fred    42
bob     9
fred    44
fred    99

и вы делаете:

SELECT col1, col2 FROM mytable GROUP BY col1;

тогда очевидно, что вы должны получить строку:

bob     9

но как насчет результата для fred? Не существует единого правильного ответа, поэтому база данных откажется выполнять такие небезопасные запросы. Если бы вы хотели величайшего col2 для любого col1 вы бы использовали max агрегатный:

SELECT col1, max(col2) AS max_col2 FROM mytable GROUP BY col1;

Недавно я перешел с MySQL на PostgreSQL и столкнулся с той же проблемой. Просто для справки, лучший подход, который я нашел, это использовать DISTINCT ON, как предложено в этом ответе SO:

Элегантная группа PostgreSQL для Ruby on Rails / ActiveRecord

Это позволит вам получить одну запись для каждого уникального значения в выбранном вами столбце, которое соответствует другим условиям запроса:

MyModel.where(:some_col => value).select("DISTINCT ON (unique_col) *") 

Я предпочитаю DISTINCT ON, потому что я все еще могу получить все другие значения столбца в строке. Только DISTINCT будет возвращать только значение этого конкретного столбца.

После частого получения ошибки я понял, что Rails (я использую rails 4) автоматически добавляет 'order by id' в конце вашего запроса на группировку. Это часто приводит к ошибке выше. Поэтому убедитесь, что вы добавляете свой собственный.order(:group_by_column) в конце вашего запроса Rails. Следовательно у вас будет что-то вроде этого:

@problems = Problem.select('problems.username, sum(problems.weight) as weight_sum').group('problems.username').order('problems.username')
Другие вопросы по тегам