web-dev-qa-db-fra.com

Rails: sélectionnez 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 de 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

220
alexandrecosta
Model.select(:rating)

Le résultat est une collection d'objets Model. Not notes simples. Et du point de vue de uniq, ils sont complètement différents. Vous pouvez utiliser ceci:

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 "niveau supérieur", comme ci-dessus. Ne fonctionne pas sur les proxy 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']
423
Sergio Tulentsev

Si vous utilisez Model.select, vous pouvez également utiliser DISTINCT, car il ne renverra que les valeurs uniques. Cela est préférable car cela signifie qu'il renvoie moins de lignes et doit être légèrement plus rapide que de renvoyer un nombre de lignes puis de demander à Rails de choisir les valeurs uniques.

Model.select('DISTINCT rating')

Bien sûr, ceci est fourni si votre base de données comprend le mot clé DISTINCT, et la plupart le devraient.

88
kakubei

Cela fonctionne aussi.

Model.pluck("DISTINCT rating")
61
Nat
Model.uniq.pluck(:rating)

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

Cela présente les avantages de ne pas utiliser de chaînes SQL et de ne pas instancier des modèles

26
Cameron Martin

Si vous souhaitez également sélectionner des champs supplémentaires:

Model.select('DISTINCT ON (models.ratings) models.ratings, models.id').map { |m| [m.id, m.ratings] }
25
Marcin Nowicki
Model.select(:rating).uniq

Ce code fonctionne comme 'DISTINCT' (pas comme Array # uniq) depuis Rails 3.2

22
kuboon

Si je vais droit au chemin alors:

Requête en cours

Model.select(:rating)

renvoie un tableau d'objet et vous avez écrit une requête

Model.select(:rating).uniq

uniq est appliqué sur un tableau d'objet et chaque objet a un identifiant unique. uniq effectue correctement son travail car chaque objet du tableau est uniq.

Il y a plusieurs façons de sélectionner un classement distinct:

Model.select('distinct rating').map(&:rating)

ou

Model.select('distinct rating').collect(&:rating)

ou

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

ou

Model.select(:name).collect(&:rating).uniq

Une dernière chose, première et deuxième requête: trouvez des données distinctes par requête SQL.

Ces requêtes seront considérées comme "londres" et "londres", ce qui signifie qu'elles négligeront l'espace. C'est pourquoi il sélectionnera "Londres" une fois dans le résultat de votre requête.

Troisième et quatrième requête:

rechercher des données par requête SQL et pour appliquer des données distinctes Ruby uniq mehtod. ces requêtes seront considérées comme "londres" et "londres" différentes, c'est pourquoi il sélectionnera "londres" et "londres" dans le résultat de votre requête.

merci de préférer l’image attachée pour plus de compréhension et jeter un oeil sur "Appel d’offres en tournée/en attente".

enter image description here

4
uma

Certaines réponses ne prennent pas en compte le PO veut un tableau de valeurs

Les autres réponses ne fonctionnent pas bien si votre modèle contient des milliers d'enregistrements.

Cela dit, je pense qu'une bonne réponse est:

    Model.uniq.select(:ratings).map(&:ratings)
    => "SELECT DISTINCT ratings FROM `models` " 

Parce que vous générez d’abord un tableau de Model (avec une taille réduite en raison de la sélection), vous extrayez ensuite le seul attribut que ces modèles sélectionnés ont (évaluations)

3
Fernando Fabreti

Si quelqu'un cherche la même chose avec Mongoid, c'est

Model.distinct(:rating)
3
Vassilis
Model.select(:rating).distinct
2
hassan_i

Une autre façon de collecter des colonnes uniques avec SQL:

Model.group(:rating).pluck(:rating)
1
Slava Zharkov