Rails: выберите уникальные значения из столбца

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

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

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

Ответ 1

Model.select(:rating)

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

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

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

Model.uniq.pluck(:rating)

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

Update

По-видимому, с рельсов 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']

Ответ 2

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

Model.select('DISTINCT rating')

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

Ответ 3

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

Model.pluck("DISTINCT rating")

Ответ 4

Model.uniq.pluck(:rating)

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

Это имеет преимущество не использовать строки sql, а не создавать экземпляры моделей

Ответ 5

Model.select(:rating).uniq

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

Ответ 6

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

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

Ответ 7

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

Model.distinct(:rating)

Ответ 8

Если я иду прямо в путь, то:

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

Model.select(:rating)

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

Model.select(:rating).uniq

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-запросу.

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

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

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

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

enter image description here

Ответ 9

Некоторые ответы не учитывают, что OP хочет массив

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

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

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

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

Ответ 10

Model.select(:rating).distinct

Ответ 11

Другой способ сбора столбцов uniq с sql:

Model.group(:rating).pluck(:rating)