Comment obtenir le dernier enregistrement de chaque groupe dans ActiveRecord?
Dans mon Ruby on Rails application j'ai une structure de base de données comme ceci:
Project.create(:group => "1", :date => "2014-01-01")
Project.create(:group => "1", :date => "2014-01-02")
Project.create(:group => "1", :date => "2014-01-03")
Project.create(:group => "2", :date => "2014-01-01")
Project.create(:group => "2", :date => "2014-01-02")
Project.create(:group => "2", :date => "2014-01-03")
# and so forth...
Comment puis-je obtenir le dernier enregistrement de chaque group
utiliser ActiveRecord?
La solution est sans doute simple, mais je ne peux pas obtenir ma tête autour de cela.
Merci pour toute aide.
- Voulez-vous être triés en fonction de leur
date
de terrain ou par le temps, les enregistrements ont été créés? - Par leur
date
champ. - Dans le cas où quelqu'un d'autre arrive à cette page, il suffit de regarder pour comment trier par dernier enregistrement sur une seule colonne (pas de regroupement), il suffit de faire quelque chose comme
Project.order(created_at: :desc).first
.
Vous devez vous connecter pour publier un commentaire.
Postgres
Dans Postgres, ce qui peut être réalisé avec la requête suivante.
Parce que le
date
colonne peut ne pas être unique ici, j'ai ajouté unORDER BY
clause surid DESC
de rompre les liens en faveur de l'enregistrement avec l'ID supérieure, dans le cas où deux enregistrements dans un groupe ont la même date. Vous devriez plutôt vous voulez utiliser une autre colonne comme la date/heure de la dernière mise à jour ou alors, cela dépend de votre cas d'utilisation.Sur la route, ActiveRecord, malheureusement, n'a pas d'API pour
DISTINCT ON
, mais on peut toujours utiliser du SQL avecselect
:ou si vous préférez utiliser ARel au lieu d'avoir cru SQL:
MySQL
Pour d'autres bases de données comme MySQL, ce n'est malheureusement pas aussi pratique. Il existe une variété de solutions disponibles, voir par exemple cette réponse.
column "projects.id" must appear in the GROUP BY clause or be used in an aggregate function
. Des idées?Project.select("DISTINCT ON(group_id) *").order("group_id, date DESC")
Project.group("group").maximum(:date)
. Il doit retourner le max date pour chaque groupe, sans en omettre aucun groupe.max
ne devrait s'appliquer qu'au sein d'un groupe.having
mais elle retourne le dossier avec la date la plus récente à partir du tableau retourné pargroup
.group
retourne un tableau de la premier enregistrement de chaque groupe.DISTINCT ON
est certainement le chemin à parcourir comme @remo suggéré. Dans MySQL et d'autres DBs c'est malheureusement plus compliqué à obtenir. L'édition de ma réponse pour refléter cela.Cela fonctionne pour moi
Quelque chose comme cela?
Cela va passer par tous vos groupes et d'identifier l'unique proches. Dans votre exemple, il devrait revenir ["1", "2"]. Puis il itère sur ce tableau et sélectionne le dernier Projet avec un id de groupe de 1, et le dernier Projet avec un id de groupe de 2.
** Mise à jour **
Viens de réaliser que vous avez dit "plus tard" et non pas "dernier" qui exige l'ajout d'une commande pour s'assurer œuvres les plus récentes. Dernière encore tire juste un.
.dernière, c'est ce que vous cherchez.
group
et obtenir les toutes dernières entrées à partir de tous groupes?