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)")
вот что я сделал.