Raylar: bir sütundan benzersiz değerler seçin


238

Zaten çalışan bir çözümüm var, ancak bunun neden işe yaramadığını bilmek istiyorum:

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

Seçer, ancak benzersiz değerleri yazdırmaz, kopyalar dahil tüm değerleri yazdırır. Ve belgelerde: http://guides.rubyonrails.org/active_record_querying.html#selecting-specific-fields


Yanıtlar:


449
Model.select(:rating)

Bunun sonucu bir Modelnesne koleksiyonudur . Düz derecelendirmeler değil. Ve uniqbakış açısından, tamamen farklılar. Bunu kullanabilirsiniz:

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

ya da bu (en verimli)

Model.uniq.pluck(:rating)

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

Güncelleme

Görünüşe göre, 5.0.0.1'den itibaren, sadece yukarıdaki gibi "üst düzey" sorgularda çalışır. Koleksiyon proxy'leri üzerinde çalışmaz (örneğin "has_many" ilişkileri).

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

Bu durumda, sorgudan sonra tekilleştirin

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

Bir grup yaptım (: rating) .collect {| r | r.rating} Harita == topladığından, kullandığınız bu sintaks hakkında nereden okuyabilirim (&: derecelendirme)? Bunu Ruby'nin belgelerinde görmüyorum.
alexandrecosta

@ user1261084: .map'i (&: derecelendirme) anlamak için # to_proc Sembolüne bakın . PragDave açıklıyor
dbenhur

63
Bunu Model.uniq.pluck(:rating)yapmanın en etkili yolu olduğunu belirtmek gerekir - bu , bir diziye SELECT DISTINCTuygulamak yerine kullanan SQL üretir.uniq
Mikey

23
Rails 5, Model.uniq.pluck(:rating)olacakModel.distinct.pluck(:rating)
nörodinamik

2
Has_many ilişkisinden benzersiz değerler seçmek isterseniz her zaman yapabilirsinizModel.related_records.group(:some_column).pluck(:some_column)
Krzysztof Karski

92

Eğer kullanacaksanız Model.select, DISTINCTsadece benzersiz değerleri döndüreceği için sadece kullanabilirsiniz . Bu daha iyidir çünkü daha az satır döndürür ve bir dizi satır döndürmekten ve sonra Rails'e benzersiz değerleri seçmesini söylemekten biraz daha hızlı olması gerektiği anlamına gelir.

Model.select('DISTINCT rating')

Tabii ki, bu veritabanı DISTINCTanahtar kelimeyi anlamak sağlanır ve çoğu gerekir.


6
Model.select("DISTINCT rating").map(&:rating)sadece derecelendirme bir dizi almak için.
Kris

Rails 2.3 kullanan eski uygulamalar olanlar için harika
Mikey

3
Evet ... bu harika çalışıyor - ancak sadece DISTINCT özniteliğini döndürüyor. Model nesnesini farklı olduğu sürece nasıl iade edebilirsiniz? Böylece, özelliğin benzersiz olduğu durumlarda modeldeki tüm özelliklere erişebileceksiniz.
zero_cool

@Jackson_Sandland Bir Model nesnesi istiyorsanız, bunun tablodaki bir kayıttan başlatılması gerekir. Ancak, yalnızca benzersiz bir değer içeren bir kayıt seçmezsiniz (birden fazla kayıt olabilen).
Benissimo


34

Ek alanlar da seçmek istiyorsanız:

Model.select('DISTINCT ON (models.ratings) models.ratings, models.id').map { |m| [m.id, m.ratings] }

1
select extra fields<3 <3
cappie013

27
Model.uniq.pluck(:rating)

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

Bu, sql dizeleri kullanmamanın ve modelleri başlatmamanın avantajlarına sahiptir


3
Bu, Rails 5.1 / AR 5.1 => undefined yöntemi `` uniq '' ile ilgili bir hata
Graham Slick


5
Model.select(:rating).distinct

2
Bu, aynı zamanda süper verimli olan tek resmi cevaptır. Her ne kadar, .pluck(:rating)sonunda eklemek OP'nin tam olarak ne istediğini yapacak.
Sheharyar

5

Ben yol doğru gidiyorum o zaman:

Mevcut sorgu

Model.select(:rating)

nesnenin dizisini döndürüyor ve sorguyu yazdınız

Model.select(:rating).uniq

uniq, nesne dizisine uygulanır ve her nesnenin benzersiz bir kimliği vardır. uniq, dizideki her nesne uniq olduğundan işini doğru şekilde gerçekleştiriyor.

Farklı derecelendirme seçmenin birçok yolu vardır:

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

veya

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

veya

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

veya

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

Bir şey daha, birinci ve ikinci sorgu: SQL sorgusu ile farklı veriler bulun.

Bu sorgular "londra" ve "londra" olarak kabul edilir, aynı zamanda uzaya ihmal edileceği anlamına gelir.

Üçüncü ve dördüncü sorgu:

SQL sorgusu ile veri bulmak ve uygulanan ayrı veriler için yakut uniq mehtod. bu sorgular "londra" ve "londra" farklı olarak kabul edilir, bu nedenle sorgu sonucunuzda "londra" ve "londra" yı seçer.

lütfen daha fazla anlayış için ekli görüntüyü tercih edin ve "Turlu / RFP'yi Bekliyor" a göz atın.

resim açıklamasını buraya girin


6
mapVe collectaynı yöntemle rumuzudur, her ikisi için örnekler sağlamak için bir ihtiyaç vardır.
Adam Lassek

4

Bazı cevaplar OP'nin bir dizi değer istediğini dikkate almaz

Modelinizde binlerce kayıt varsa diğer yanıtlar işe yaramaz

Bununla birlikte, bence iyi bir cevap:

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

İlk olarak, bir Model dizisi (seçim nedeniyle küçültülmüş boyutta) oluşturduğunuz için, seçilen modellerin sahip olduğu tek özelliği (derecelendirmeler) çıkarırsınız


3

Eğer kimse Mongoid ile aynı şeyi arıyorsa,

Model.distinct(:rating)

bu şimdi çalışmıyor, şimdi katları döndürüyor.
EUPHORAY

farklı
dönmüyor

2

Sql ile benzersiz sütunları toplamanın başka bir yolu:

Model.group(:rating).pluck(:rating)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.