Рельсы: выберите уникальные значения из столбца - PullRequest
218 голосов
/ 12 марта 2012

У меня уже есть работающее решение, но я действительно хотел бы знать, почему это не работает:

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

Он выбирает, но не печатает уникальные значения, он печатает все значения, включаядубликаты.И это в документации: http://guides.rubyonrails.org/active_record_querying.html#selecting-specific-fields

Ответы [ 11 ]

419 голосов
/ 12 марта 2012
Model.select(:rating)

В результате получается коллекция Model объектов.Непонятные рейтинги.А с точки зрения uniq они совершенно разные.Вы можете использовать это:

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

или это (наиболее эффективное)

Model.uniq.pluck(:rating)

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

Обновление

По-видимому, с рельсов 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']
88 голосов
/ 05 ноября 2012

Если вы собираетесь использовать Model.select, то вы можете просто использовать DISTINCT, поскольку он будет возвращать только уникальные значения.Это лучше, потому что это означает, что он возвращает меньше строк и должен быть немного быстрее, чем возвращать количество строк, а затем указывать Rails выбрать уникальные значения.

Model.select('DISTINCT rating')

Конечно, это при условии, что ваша база данных понимает ключевое слово DISTINCT, и большинство должно.

61 голосов
/ 12 ноября 2012

Это тоже работает.

Model.pluck("DISTINCT rating")
26 голосов
/ 19 марта 2014
Model.uniq.pluck(:rating)

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

Преимущество этого состоит в том, что не используются строки SQL и не создаются модели

23 голосов
/ 05 мая 2015

Если вы также хотите выбрать дополнительные поля:

Model.select('DISTINCT ON (models.ratings) models.ratings, models.id').map { |m| [m.id, m.ratings] }
21 голосов
/ 11 июля 2012
Model.select(:rating).uniq

Этот код работает как 'DISTINCT' (не как Array # uniq), поскольку rails 3.2

4 голосов
/ 14 марта 2014

Если я пойду направо, то:

Текущий запрос

Model.select(:rating)

возвращает массив объекта, и вы написали запрос

Model.select(:rating).uniq

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

Еще одна вещь, первый и второй запрос: найти отличные данные по SQL-запросу.

Эти запросы будут считаться "london" и "london" одинаковыми, то есть они будут пренебрегать пробелом, поэтому он выберет 'london' один раз в результатах вашего запроса.

Третий и четвертый запрос:

поиск данных по запросу SQL и для отдельных данных применяется метод ruby ​​uniq. эти запросы будут считать «лондон» и «лондон» разными, поэтому в результатах запроса будут выбраны «лондон» и «лондон».

Пожалуйста, предпочитайте прикрепленное изображение для большего понимания и посмотрите "Toured / Awaiting RFP".

enter image description here

3 голосов
/ 25 апреля 2015

В некоторых ответах не учитывается, что ОП хочет массив значений

Другие ответы не работают, если в вашей модели тысячи записей

Тем не менее, я думаю, что хороший ответ:

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

Потому что сначала вы генерируете массив Model (с уменьшенным размером из-за выбора), затем вы извлекаете единственный атрибут, который имеют выбранные модели (оценки)

3 голосов
/ 08 июля 2014

Если кто-то ищет то же самое с Mongoid, то это

Model.distinct(:rating)
1 голос
/ 09 августа 2017

Еще один способ собрать уникальные столбцы с помощью sql:

Model.group(:rating).pluck(:rating)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...