GroupingError: ERROR: столбец должен отображаться в предложении GROUP BY или использоваться в агрегатной функции
У меня есть код в моем контроллере, который ранжирует альбомы по самым высоким средним рейтингам обзора (используется код из этого решения Как отображать альбомы с наивысшим рейтингом через отношения с просмотром has_many):
@albums = Album.joins(:reviews).select("*, avg(reviews.rating) as average_rating").group("albums.id").order("average_rating DESC")
Этот код отлично работает в моей среде разработки (sqlite3), однако, когда я нажал код на герою и на postgresql, я получил эту ошибку:
PG::GroupingError: ERROR: column "reviews.id" must appear in the GROUP BY clause or be used in an aggregate function
Я понимаю, что это довольно распространенная проблема, я немного неопытен SQL, поэтому мне трудно реорганизовать код, чтобы он работал как в моей среде разработки, так и в производственной среде.
Ответы
Ответ 1
Вам не разрешено выбирать reviews.id
(выбранный неявно через подстановочный знак *
), не добавляя его в предложение GROUP BY
или применяя агрегатную функцию, например avg()
. Решение состоит в том, чтобы выполнить одно из следующих действий:
- Удалите подстановочный знак
*
из выбранного
- Добавить поле
reviews.id
в предложение группы
- Выделите
reviews.id
явно и примените к нему агрегатную функцию (например, sum(reviews.id)
)
- Замените подстановочный знак
*
специальным шаблоном для таблицы albums.*
Второй и третий варианты не имеют особого смысла в вашем сценарии.
Основываясь на вашем комментарии, я добавил вариант 4.
Ответ 2
Просто хотел бы поделиться этим кодом на ruby, используя активную запись (sinatra)
Мне пришлось добавить "group by" к функции "order by", поэтому строка кода...
от
@models = Port.all.order('number asc')
в
@models = Port.select(:id, :device_id, :number, :value, :sensor, :UOM).all.order('number asc').group(:id,:sensor,:UOM)
и он отлично работает, просто запомните поле ID в этом случае "Port.id" должно быть добавлено в предложение group, иначе это приведет к повышению этой ошибки, и, как упоминалось в @slash, вы не можете добиться этого с помощью специальных функций (выберите неявно через подстановочный знак * или в моем случае, используя "все" )
Ответ 3
Единственное действительно приемлемое решение, которое я нашел для этой проблемы, было с этим кодом:
@albums = Album.joins(:reviews).select("*, avg(reviews.rating) as average_rating").group_by(&:id).order("average_rating DESC")
Я надеюсь, что это поможет кому-то.