J'ai dans mon contrôleur un code qui classe les albums en fonction de la note moyenne la plus élevée (code utilisé dans cette solution Comment afficher les albums les mieux notés via une relation has_many reviews ):
@albums = Album.joins(:reviews).select("*, avg(reviews.rating) as average_rating").group("albums.id").order("average_rating DESC")
Ce code fonctionne parfaitement dans mon environnement de développement (sqlite3). Cependant, lorsque j'ai transmis le code à heroku et à postgresql, j'ai obtenu cette erreur:
PG::GroupingError: ERROR: column "reviews.id" must appear in the GROUP BY clause or be used in an aggregate function
Je me rends compte que c'est un problème assez courant, je suis un peu inexpérimenté avec SQL et j'ai donc du mal à refactoriser le code afin que cela fonctionne dans les environnements de développement et de production.
Vous n'êtes pas autorisé à sélectionner reviews.id
(sélectionné implicitement via le caractère générique *
) sans l'ajouter à la clause GROUP BY
ni appliquer une fonction d'agrégation telle que avg()
. La solution consiste à effectuer l'une des opérations suivantes:
*
de votre sélectionreviews.id
à votre clause de groupereviews.id
explicitement et appliquez-lui une fonction d'agrégat (par exemple, sum(reviews.id)
) *
par le caractère générique propre à la table albums.*
La deuxième et la troisième option n’ont pas beaucoup de sens dans votre scénario cependant… .. Sur la base de votre commentaire, j’ai ajouté l’option quatre.
Je voudrais juste partager ce code sur Ruby en utilisant un enregistrement actif (sinatra)
Je devais ajouter "group by" à une fonction "order by", donc ligne de code ...
de:
@models = Port.all.order('number asc')
à:
@models = Port.select(:id, :device_id, :number, :value, :sensor, :UOM).all.order('number asc').group(:id,:sensor,:UOM)
et cela a fonctionné parfaitement, rappelez-vous simplement que le champ ID dans ce cas, "Port.id" doit être ajouté à la clause group sinon cette erreur sera générée, et comme @slash l'a mentionné, vous ne pouvez pas y parvenir avec des fonctions spéciales (sélectionnez implicitement dans le caractère générique. * ou dans mon cas en utilisant "tous")
La seule solution vraiment acceptable que j'ai trouvée à ce genre de problème était avec ce code:
@albums = Album.joins(:reviews).select("*, avg(reviews.rating) as average_rating").group_by(&:id).order("average_rating DESC")
J'espère que ça aide quelqu'un.