273 votes

Rails : sélectionner des valeurs uniques dans une colonne

J'ai déjà une solution qui fonctionne, mais j'aimerais vraiment savoir pourquoi cela ne fonctionne pas :

ratings = Model.select(:rating).uniq
ratings.each { |r| puts r.rating }

Il sélectionne, mais n'imprime pas les valeurs uniques, il imprime toutes les valeurs, y compris les doublons. Et c'est dans la documentation : http://guides.rubyonrails.org/active_record_querying.html#selecting-specific-fields

532voto

Sergio Tulentsev Points 82783
Model.select(:rating)

Le résultat de cette démarche est une collection de Model objets. Pas de simples notes. Et de uniq Du point de vue de l'auteur, ils sont complètement différents. Tu peux utiliser ça :

Model.select(:rating).map(&:rating).uniq

ou ceci (le plus efficace) :

Model.uniq.pluck(:rating)

Rails 5+.

Model.distinct.pluck(:rating)

Mise à jour

Apparemment, à partir de rails 5.0.0.1, cela ne fonctionne que sur les requêtes de "haut niveau", comme ci-dessus. Il ne fonctionne pas sur les proxies de collection (relations "has_many", par exemple).

Address.distinct.pluck(:city) # => ['Moscow']
user.addresses.distinct.pluck(:city) # => ['Moscow', 'Moscow', 'Moscow']

Dans ce cas, dédupliquer après la requête

user.addresses.pluck(:city).uniq # => ['Moscow']

102voto

kakubei Points 1526

Si vous voulez utiliser Model.select alors vous pouvez tout aussi bien utiliser DISTINCT car il ne retournera que les valeurs uniques. C'est mieux ainsi car cela signifie qu'elle renvoie moins de lignes et devrait être légèrement plus rapide que de renvoyer un certain nombre de lignes et de demander ensuite à Rails de sélectionner les valeurs uniques.

Model.select('DISTINCT rating')

Bien entendu, ceci est conditionné par le fait que votre base de données comprenne l'option DISTINCT mot-clé, et la plupart le devraient.

75voto

Nat Points 643

Cela fonctionne aussi.

Model.pluck("DISTINCT rating")

27voto

Cameron Martin Points 826
Model.uniq.pluck(:rating)

# SELECT DISTINCT "models"."rating" FROM "models"

Cette méthode présente l'avantage de ne pas utiliser de chaînes sql et de ne pas instancier de modèles.

24voto

kuboon Points 1033
Model.select(:rating).uniq

Ce code fonctionne comme 'DISTINCT' (et non comme Array#uniq) puisque rails 3.2

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X