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

Я получаю эту ошибку в режиме производства pg, но она отлично работает в режиме разработки 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 ответов


если 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" в конце вашего группового запроса. Это часто приводит к ошибке выше. Поэтому убедитесь, что вы добавляете свой собственный .заказ (: group_by_column) в конце запроса Rails. Следовательно, у вас будет что-то вроде этого:

@problems = Problem.select('problems.username, sum(problems.weight) as weight_sum').group('problems.username').order('problems.username')

@myestate1 = Estate.where(:Mgmt => current_user.Company)
@myestate = @myestate1.select("DISTINCT(user_id)")

вот что я сделал.