J'obtiens cette erreur dans le mode de production de pg, mais son fonctionnement très bien dans le mode de développement 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
@myestate1 = Estate.where(:Mgmt => current_user.Company)
@myestate = @myestate1.select("DISTINCT(user_id)")
c'est ce que j'ai fait.
Si user_id
est la CLÉ PRIMAIRE alors vous devez mettre à jour PostgreSQL; les versions plus récentes gèreront correctement le regroupement par la clé primaire.
Si user_id
n'est ni unique ni la clé primaire de la relation 'successions' en question, alors cette requête ne fait pas beaucoup de sens, car PostgreSQL n'a aucun moyen de savoir quelle valeur renvoyer pour chaque colonne de estates
où plusieurs lignes partagent la même user_id
. Vous devez utiliser une fonction d'agrégation qui exprime ce que vous voulez, comme min
, max
, avg
, string_agg
, array_agg
, etc. ou ajoutez la ou les colonnes qui vous intéressent dans le GROUP BY
.
Vous pouvez également reformuler la requête pour utiliser DISTINCT ON
Et un ORDER BY
si vous voulez vraiment choisir une ligne quelque peu arbitraire, bien que je doute vraiment qu'il soit possible de l'exprimer via ActiveRecord.
Certaines bases de données - y compris SQLite et MySQL - choisiront simplement une ligne arbitraire. Ceci est considéré comme incorrect et dangereux par l'équipe de PostgreSQL, donc PostgreSQL suit le standard SQL et considère ces requêtes comme des erreurs.
Si tu as:
col1 col2
fred 42
bob 9
fred 44
fred 99
et vous faites:
SELECT col1, col2 FROM mytable GROUP BY col1;
alors il est évident que vous devriez obtenir la ligne:
bob 9
mais qu'en est-il du résultat pour fred
? Il n'y a pas de réponse correcte unique à choisir, donc la base de données refusera d'exécuter de telles requêtes dangereuses. Si vous vouliez le plus grand col2
pour toute col1
vous utiliseriez l'agrégat max
:
SELECT col1, max(col2) AS max_col2 FROM mytable GROUP BY col1;
J'ai récemment migré de MySQL vers PostgreSQL et rencontré le même problème. Juste pour référence, la meilleure approche que j'ai trouvée est d'utiliser DISTINCT ON comme suggéré dans cette réponse SO:
Groupe PostgreSQL élégant par pour Ruby on Rails/ActiveRecord
Cela vous permettra d'obtenir un enregistrement pour chaque valeur unique dans votre colonne choisie qui correspond aux autres conditions de requête:
MyModel.where(:some_col => value).select("DISTINCT ON (unique_col) *")
Je préfère DISTINCT ON car je peux toujours obtenir toutes les autres valeurs de colonne de la ligne. DISTINCT seul ne renverra que la valeur de cette colonne spécifique.
Après avoir souvent reçu l'erreur moi-même, je me suis rendu compte que Rails (J'utilise Rails 4) ajoute automatiquement un 'ordre par id' à la fin de votre requête de regroupement) . Cela entraîne souvent l'erreur ci-dessus. Assurez-vous donc d'ajouter votre propre .order (: group_by_column) à la fin de votre requête Rails. Par conséquent, vous aurez quelque chose comme ceci:
@problems = Problem.select('problems.username, sum(problems.weight) as weight_sum').group('problems.username').order('problems.username')