Rails 3.1 с PostgreSQL: GROUP BY должна использоваться в статистической функции - PullRequest
7 голосов
/ 05 августа 2011

Я пытаюсь загрузить последние 10 искусств, сгруппированных по user_id и упорядоченных созданным Это прекрасно работает с SqlLite и MySQL, но выдает ошибку в моей новой базе данных PostgreSQL.

Art.all(:order => "created_at desc", :limit => 10, :group => "user_id")

Ошибка ActiveRecord:

Art Load (18.4ms)  SELECT "arts".* FROM "arts" GROUP BY user_id ORDER BY created_at desc LIMIT 10
ActiveRecord::StatementInvalid: PGError: ERROR:  column "arts.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT  "arts".* FROM "arts"  GROUP BY user_id ORDER BY crea...

Есть идеи?

Ответы [ 4 ]

8 голосов
/ 05 августа 2011

SQL, сгенерированный выражением, не является допустимым запросом, вы группируете по user_id и выбираете множество других полей на основе этого, но не указываете БД, как следует агрегировать другие поля. Например, если ваши данные выглядят так:

a  | b
---|---
1  | 1
1  | 2
2  | 3

Теперь, когда вы просите db сгруппировать по a и также вернуть b, он не знает, как агрегировать значения 1,2. Вы должны сказать, нужно ли выбирать минимальное, максимальное, среднее, сумму или что-то еще. Когда я писал ответ, было два ответа, которые могли бы объяснить все это лучше.

В вашем случае, я думаю, вы не хотите группировать на уровне БД. Поскольку существует всего 10 искусств, вы можете сгруппировать их в своем приложении. Не используйте этот метод с тысячами искусств, хотя:

 arts = Art.all(:order => "created_at desc", :limit => 10)
 grouped_arts = arts.group_by {|art| art.user_id}
 # now you have a hash with following structure in grouped_arts
 # { 
 #    user_id1 => [art1, art4],
 #    user_id2 => [art3],
 #    user_id3 => [art5],
 #    ....
 # }

РЕДАКТИРОВАТЬ: Выберите последние_арты, но только один рисунок на пользователя

Просто для того, чтобы дать вам представление о SQL (не тестировал его, так как в моей системе не установлено СУБД)

SELECT arts.* FROM arts
WHERE (arts.user_id, arts.created_at) IN 
  (SELECT user_id, MAX(created_at) FROM arts
     GROUP BY user_id
     ORDER BY MAX(created_at) DESC
     LIMIT 10)
ORDER BY created_at DESC
LIMIT 10

Это решение основано на практическом предположении, что никакие два искусства для одного и того же пользователя не могут иметь одинаковый наивысший созданный_кат, но это может быть неправильно, если вы импортируете или программно создаете большую часть искусств. Если предположение не выполняется, sql может стать более надуманным.

РЕДАКТИРОВАТЬ: Попытка изменить запрос на Arel:

Art.where("(arts.user_id, arts.created_at) IN 
             (SELECT user_id, MAX(created_at) FROM arts
                GROUP BY user_id
                ORDER BY MAX(created_at) DESC
                LIMIT 10)").
    order("created_at DESC").
    page(params[:page]).
    per(params[:per])
5 голосов
/ 11 сентября 2014

Вам нужно выбрать нужные колонки

Art.select (: идентификатор_пользователь) .group (: идентификатор_пользователь) .limit (10)

Ошибка при попытке выбрать заголовок в запросе, например

Art.select (: user_id,: title) .group (: user_id) .limit (10)

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

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

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

Art.select (: user_id,: title) .group (: user_id,: title) .limit (10)

или использоваться в статистической функции

Art.select ("user_id, array_agg (title) в качестве заголовков"). Group (: user_id) .limit (10)

2 голосов
/ 05 августа 2011

Взгляните на этот пост. SQLite для Postgres (Heroku) GROUP BY

PostGres на самом деле следует стандарту SQL, тогда как sqlite и mysql выходят за рамки стандарта.

0 голосов
/ 05 августа 2011

Посмотрите на этот вопрос - Преобразование MySQL в PostgreSQL .Postgres не разрешит указывать столбец в операторе select, которого нет в предложении group by.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...