web-dev-qa-db-ja.com

レール:列から一意の値を選択します

私はすでに実用的な解決策を持っていますが、なぜこれがうまくいかないのかを知りたいです。

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

選択しますが、一意の値は表示しません。重複を含むすべての値を表示します。そしてそれはドキュメントにあります。 http://guides.rubyonrails.org/active_record_querying.html#selecting-specific-fields

215
alexandrecosta
Model.select(:rating)

これの結果はModelオブジェクトのコレクションです。明白な評価ではありません。そしてuniqの観点からは、それらは完全に異なります。これを使うことができます:

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

またはこれ(最も効率的)

Model.uniq.pluck(:rating)

# Rails 5+
Model.distinct.pluck(:rating)

更新

どうやら、Rails 5.0.0.1以降では、上記のように "トップレベル"のクエリでしか動作しません。コレクションプロキシ(たとえば "has_many"リレーション)には作用しません。

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

この場合は、クエリの後で重複排除します

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

Model.selectを使うつもりなら、DISTINCTを使ってもいいでしょう。ユニークな値しか返さないからです。これはより少ない行数を返すことを意味し、いくつかの行数を返してRailsに一意の値を選択するように指示するよりもわずかに速いはずです。

Model.select('DISTINCT rating')

もちろん、これはあなたのデータベースがDISTINCTキーワードを理解するために提供されており、ほとんどはそうすべきです。

85
kakubei

これもうまくいきます。

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

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

これは、SQL文字列を使用せず、モデルをインスタンス化しないという利点があります。

26
Cameron Martin

追加のフィールドも選択したい場合は、

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

Rails 3.2 から、このコードは(Array#uniqではなく) 'DISTINCT'として機能します。

21
kuboon

私が順調に進んでいるなら:

現在のクエリ

Model.select(:rating)

オブジェクトの配列を返している、あなたはクエリを書いている

Model.select(:rating).uniq

uniqはオブジェクトの配列に適用され、各オブジェクトは一意のIDを持ちます。配列内の各オブジェクトはuniqであるため、uniqはそのジョブを正しく実行しています。

明確な評価を選択するには多くの方法があります。

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

または

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

または

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

または

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

もう1つ、1番目と2番目のクエリ:SQLクエリによって異なるデータを見つける。

これらのクエリは "london"と "london"が同じであると見なされますが、スペースを無視することを意味します。そのため、クエリ結果で一度に "london"を選択します。

3番目と4番目のクエリ:

sQLクエリとRuby uniq mehtodを適用した明確なデータのためのデータ検索これらのクエリでは "london"と "london"が異なると見なされるため、クエリ結果で 'london'と 'london'が選択されます。

理解を深めるために添付画像をご希望の場合は、「Toured/Awaiting RFP」をご覧ください。

enter image description here

4
uma

いくつかの答えは、OPが望んでいることを考慮に入れていない値の配列

モデルに何千ものレコードがある場合、他の回答はうまく機能しません。

それは言った、私は良い答えがあると思います:

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

なぜなら、最初にModelの配列(selectのためにサイズが縮小されている)を生成し、次にそれらの選択されたモデルが持つ唯一の属性(rating)を抽出するからです。

3

誰かがMongoidで同じことを探しているなら、それは

Model.distinct(:rating)
3
Vassilis

Sqlを使ってユニークなカラムを集めるもう一つの方法:

Model.group(:rating).pluck(:rating)
1
Slava Zharkov
Model.select(:rating).distinct
1
hassan_i