J'ai un modèle, ConnectedUser
, qui appartient à 2 autres modèles User
et Station
.
C'est un modèle simple avec juste ces relations et un booléen active
.
Les résultats de la requête que je vise ne seraient que chaque enregistrement ConnectedUser
le plus récent pour chaque User (où la Station
est un identifiant spécifique).
Par exemple, si ma table ConnectedUser
ressemblait à ceci. .
ConnectedUser.where(station: station).select(:user_id).group(:user_id).order(:created_at)
Et la station était celle avec l'identifiant 1 alors j'aimerais que la requête retourne ...
[ <ConnectedUser id: 1, user_id: 1, station_id: 1, active: true, created_at: "2019-06-20">, <ConnectedUser id: 5, user_id: 2, station_id: 1, active: false, created_at: "2019-06-21"> ]
Pour y parvenir, j'ai essayé d'utiliser group
pour et order
+----+---------+------------+--------+------------+ | id | user_id | station_id | active | created_at | +----+---------+------------+--------+------------+ | 1 | 1 | 1 | true | 20 June | | 2 | 1 | 1 | false | 19 June | | 3 | 1 | 2 | false | 20 June | | 4 | 2 | 1 | false | 18 June | | 5 | 2 | 1 | false | 21 June | +----+---------+------------+--------+------------+
mais j'ai continué à recevoir des erreurs comme ceci:
ActiveRecord :: StatementInvalid (PG :: GroupingError: ERROR: colonne "connected_users.created_at" doit apparaître dans la clause GROUP BY ou être utilisé dans une fonction d'agrégation)
Je ne parviens pas à obtenir l'identifiant spécifique de ConnectedUser
, alors j'ai l'impression que je manque de connaissances importantes sur la manière de travailler avec group
et d'agréger les résultats .
Est-ce possible dans une seule requête ActiveRecord?
Merci beaucoup.
3 Réponses :
Dans Postgres, si vous voulez la version la plus récente pour chaque utilisateur / poste, je recommanderais distinct sur
:
select distinct on (station_id, user_id) cu.* from ConnectedUser cu order by station_id, user_id, created_at desc;
Merci, j'aimerais utiliser la requête ActiveRecord si possible afin de pouvoir passer la station
via des paramètres.
Vous devez utiliser DISTINCT ON
au lieu de GROUP
. Voici comment vous pouvez le faire dans Rails:
ConnectedUser.select("DISTINCT ON (station_id, user_id) *") .where(station_id: params[:station_id]) .order(created_at: :desc)
Bien sûr, avec params [: station_id]
c'est ce que vous voulez filtrer
Merci d'essayer que ConnectedUser.select ("DISTINCT ON (station_id, user_id)"). Where (station: station) .order (created_at:: desc)
me donne cette erreur cependant ... < code> ActiveRecord :: StatementInvalid (PG :: SyntaxError: ERROR: erreur de syntaxe à ou près de "FROM") LINE 1: SELECT DISTINCT ON (station_id, user_id) FROM "connected_use ...
Ouais, il semble que j'ai oublié le caractère * dans l'instruction select. Veuillez consulter ma réponse mise à jour et voir si cela fonctionne maintenant
Probablement, cela résoudrait le problème
ConnectedUser.where (active: true) .order (user_id:: desc) .uniq (&: user_id)
order
est utilisé pour trier le champ user_id
dans DESC
sur cette solution, j'utilise uniq
, qui est une solution de tableau, et je ne sélectionnerai que le plus récent user_id
modifier:
J'avais tort, uniq ne fonctionnait pas comme prévu, mais en testant ici, je découvre que:
ConnectedUser.where (active: true) .order (created_at:: desc) .group (: user_id)
ressemble beaucoup au vôtre, mais, lorsque vous utilisez select, il ne sélectionne que le champ user_id, donc vous ne pouvez pas commander par created_at
Devrait fonctionner
Merci, utiliser uniq
semble intéressant mais je pense que uniq
est désormais obsolète au profit de distinct
. En l'essayant, il ne semble pas non plus renvoyer les enregistrements les plus récents, mais la commande par created_at n'a pas semblé aider.
Bonjour, avec la version modifiée, je reçois à nouveau l'erreur familière que j'ai essayé de résoudre: (PG :: GroupingError: ERROR: la colonne "connected_users.id" doit apparaître dans la clause GROUP BY ou être utilisé dans une fonction d'agrégation)
merci d'avoir essayé.
@Chris, et si vous essayez de mettre id
dans le groupe, comme group (: id,: user_id)
?
Oui, j'ai essayé cette approche et ses variantes, sans aucune chance. Merci encore.
Toutes mes excuses, cela ne devrait pas changer, j'ai édité pour corriger cela.