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)