web-dev-qa-db-fra.com

Requête Rails 4 unique par attribut unique

C’est donc plus une question d’arel qu’autre chose, mais voici ce que j’essaie de faire.

J'ai trois objets, disons, appelés Items

<Item id: 1, name: 'Book'>
<Item id: 2, name: 'Car'>
<Item id: 3, name: 'Book'>

Je souhaite effectuer une requête qui ne renverra qu'un seul de chaque attribut unique "name".

Quelque chose comme Item.select('distinct(name), items.*')

Cela ne fonctionne pas bien, il renvoie toujours les trois éléments.

Comment puis-je former cette requête afin qu'elle ne retourne que:

<Item id: 1, name: 'Book'>
<Item id: 2, name: 'Car'>
20
goddamnyouryan

Si vous souhaitez récupérer le modèle entier tout en conservant l'unicité, vous pouvez utiliser ceci:

Item.select('distinct on (name) *')

Je n'ai testé cela qu'avec une base de données Postgres. Cela peut ou peut ne pas fonctionner avec mysql.

30
BananaNeil

S'il vous plaît essayez ceci:

Item.select('distinct name')
11
vee

Si vous avez seulement besoin d'un tableau avec les noms, sans l'ID, vous pouvez faire:

Item.pluck(:name).uniq

Résultat de la requête SQL:

#=> SELECT `items`.`name` FROM `items`

** modifier **

La uniq est exécutée sur le tableau d'enregistrements. Faites attention si vous attendez beaucoup de disques. SQL Distinct est beaucoup plus rapide.

Si oui, utilisez la réponse de vee ci-dessus, avec un map:

Item.select('distinct name').map(:name)

4
Frexuz

Dans Rails 4, essayez Items.all.to_a.uniq { |item| item.name }

Dans Rails 3, vous devriez pouvoir faire Items.uniq_by { |item| item.name }

Lorsque vous appelez uniq sur un tableau, vous pouvez lui transmettre un bloc pour indiquer comment déterminer l'unicité. Dans Rails 3, vous pouviez utiliser uniq_by, mais il est devenu obsolète dans Rails 4. Une méthode que j’ai trouvée consiste donc à convertir la relation ActiveRecord en un tableau et à appeler uniq à ce sujet.

2
TalkativeTree

Ce qui suit est une requête ORM ORM qui produira le résultat souhaité avec toutes les dernières versions de Rails Rails 5.X.

@unique_values= []
Model.all.group_by(&:column_name).each do |key, val|
    if val.count == 1
      @unique_values << val
    else
      @unique_values << val.first
    end
end
0
Ankit Varshney

Pour Mysql, vous pouvez utiliser group avec ONLY_FULL_GROUP_BY disabled,

Item.group(:name).to_sql
=> "SELECT `items`.* FROM `items`  GROUP BY name"

Voir Existe-t-il une capacité ANY_VALUE pour mysql 5.6?

0
fangxing